/// <summary> /// Demote: Decrease the rank of a guild member. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Demote(CharData ch, string[] str) { if( ch == null ) return; SocketConnection victimSocket; int count; bool loggedIn = false; if (str.Length == 0) { ch.SendText("Demote whom?\r\n"); return; } if (!ch.IsGuild() || ((PC)ch).GuildRank != Guild.Rank.leader) { ch.SendText("You don't have the power to do this.\r\n"); return; } Guild guild = ((PC)ch).GuildMembership; CharData victim = null; foreach (CharData worldChar in Database.CharList) { if (worldChar.IsNPC()) { continue; } if (MUDString.NameContainedIn(str[0], worldChar.Name)) { victim = worldChar; loggedIn = true; break; } } if (victim == null) { if (!(CharData.LoadPlayer((victimSocket = new SocketConnection()), str[0]))) { ch.SendText("Who's that?!\r\n"); return; } victim = victimSocket.Original ? victimSocket.Original : victimSocket.Character; loggedIn = false; } if (victim.IsNPC()) { ch.SendText("NPCs are not guildable!\r\n"); return; } if (!ch.IsSameGuild(victim)) { SocketConnection.Act("$N&n isn't even from $t.", ch, guild.WhoName, victim, SocketConnection.MessageTarget.character); return; } switch (((PC)victim).GuildRank) { default: ch.SendText("You can't demote this person.\r\n"); return; case Guild.Rank.normal: ch.SendText("You can't demote them any further.\r\n"); return; case Guild.Rank.senior: case Guild.Rank.officer: case Guild.Rank.deputy: break; case Guild.Rank.leader: if (str.Length > 1 && MUDString.StringsNotEqual(str[1], "confirm")) { ch.SendText("Try 'demote leadername confirm' to demote a leader.\r\n"); return; } break; } ((PC)victim).GuildRank--; Guild.Rank newrank = ((PC)victim).GuildRank; SetTitle(victim, guild.RankNames[(int)((PC)victim).GuildRank]); string text = String.Format("Log {0}: demoting {1} to {2}", ch.Name, victim.Name, ((PC)ch).GuildMembership.Name); Database.LogGuild(text); text = String.Format( "The grand Overlord {0} says:\r\n\r\n" + "'I hereby demote you {1} to {2}!!!'\r\n" + "You should make more efforts to improve!", ch.Name, victim.Name, newrank); if (loggedIn) { victim.SendText(text); } SocketConnection.Act("You have demoted $N to $t.", ch, newrank.ToString(), victim, SocketConnection.MessageTarget.character); for (count = 0; count < Limits.MAX_GUILD_MEMBERS; ++count) { if (!MUDString.StringsNotEqual(guild.Members[count].Name, victim.Name)) { guild.Members[count].Rank = ((PC)victim).GuildRank; } } CharData.SavePlayer(victim); guild.Save(); /* Close rented chars pfile. */ if (!loggedIn) { victimSocket = null; } return; }
/// <summary> /// Exile a player from a guild. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Exile(CharData ch, string[] str) { if( ch == null ) return; if (str.Length == 0) { ch.SendText("Exile whom?\r\n"); return; } if (!ch.IsGuild() || ((PC)ch).GuildRank != Guild.Rank.leader) { ch.SendText("You don't have the power to do this.\r\n"); return; } Guild guild = ((PC)ch).GuildMembership; CharData victim = ch.GetCharWorld(str[0]); if (!victim) { ch.SendText("They aren't here.\r\n"); return; } if (victim.IsNPC() || victim == ch || victim.Level > ch.Level) return; if (!ch.IsSameGuild(victim)) { SocketConnection.Act("$N isn't even from $t.", ch, guild.WhoName, victim, SocketConnection.MessageTarget.character); return; } string text = String.Format("Log {0}: exiling {1} from {2}", ch.Name, victim.Name, ((PC)ch).GuildMembership.Name); Database.LogGuild(text); // This function handles resetting member data victim.RemoveFromGuild(); ((PC)victim).GuildRank = Guild.Rank.exiled; text = String.Format( "The grand Overlord of {0} {1} says:\r\n\r\n" + "'Then so be done, you {2} shall be exiled from {3}!'\r\n" + "You hear a thundering sound...\r\n\r\n" + "A booming voice says: 'You have been exiled. Only the gods can allow you\r\n" + "to join another clan, order or guild!'\r\n", guild.WhoName, guild.Overlord, victim.Name, guild.WhoName); victim.SendText(text); SocketConnection.Act("You have exiled $N&n from $t!", ch, guild.WhoName, victim, SocketConnection.MessageTarget.character); CharData.SavePlayer(victim); guild.Save(); return; }
public static void Socname(CharData ch, string[] str) { if( ch == null ) return; string arg = String.Empty; Guild.Rank rank; if (!ch.IsGuild() || ((PC)ch).GuildRank < Guild.Rank.leader) { ch.SendText("You don't have the power to do this.\r\n"); return; } if (arg.Length == 0) { ch.SendText("Reset the title on which rank?\r\n"); return; } Guild guils = ((PC)ch).GuildMembership; try { rank = (Guild.Rank)Enum.Parse(typeof(Guild.Rank), arg, false); } catch (Exception) { ch.SendText("That's not a valid rank.\r\n"); return; } if (str.Length == 0) { ch.SendText("Set the rank title to what?\r\n"); return; } guils.RankNames[(int)rank] = str[0]; ch.SendText("Done.\r\n"); guils.Save(); return; }
public static void Channels(CharData ch, string[] str) { if( ch == null ) return; if (str.Length == 0 || String.IsNullOrEmpty(str[0])) { if (!ch.IsNPC() && ch.HasActionBit(PC.PLAYER_SILENCE)) { ch.SendText("&nYou are silenced, cur.\r\n"); return; } ch.SendText("Channels:"); ch.SendText(ch.IsListening(TalkChannel.shout) ? " +SHOUT" : " -shout"); ch.SendText(ch.IsListening(TalkChannel.yell) ? " +YELL" : " -yell"); if (ch.IsGuild()) { ch.SendText(ch.IsListening(TalkChannel.guild) ? " +guild" : " -guild"); } if (ch.IsHero()) { ch.SendText(ch.IsListening(TalkChannel.immortal) ? " +IMMTALK" : " -immtalk"); } ch.SendText(".\r\n"); } else { TalkChannel bit; bool fClear; if (str[0][0] == '+') fClear = true; else if (str[0][0] == '-') fClear = false; else { ch.SendText("&nChannels -channel or +channel?\r\n"); return; } string tmparg = String.Format("{0}", str[0]); if (!MUDString.StringsNotEqual(tmparg + 1, "immtalk")) bit = TalkChannel.immortal; else if (!MUDString.StringsNotEqual(tmparg + 1, "guild")) bit = TalkChannel.guild; else if (!MUDString.StringsNotEqual(tmparg + 1, "shout")) bit = TalkChannel.shout; else if (!MUDString.StringsNotEqual(tmparg + 1, "yell")) bit = TalkChannel.yell; else { ch.SendText("&nSet or clear which channel?\r\n"); return; } if (fClear) ch.SetListening(bit, true); else ch.SetListening(bit, false); ch.SendText("&nOk.\r\n"); } return; }
public static void Ostracize(CharData ch, string[] str) { if( ch == null ) return; string arg = String.Empty; if (!ch.IsGuild() || ((PC)ch).GuildRank < Guild.Rank.deputy) { ch.SendText("You don't have the power to do this.\r\n"); return; } if (arg.Length == 0) { ch.SendText("Who do you want to ostracize?\r\n"); return; } Guild guild = ((PC)ch).GuildMembership; if (MUDString.NameContainedIn(arg, guild.Ostracized)) { ch.SendText("They've already been ostracized.\r\n"); return; } string buf = String.Format("{0} {1}", guild.Ostracized, arg); if (!MUDString.StringsNotEqual(arg, "clear")) { buf = String.Empty; } guild.Ostracized = buf; ch.SendText("Done.\r\n"); guild.Save(); return; }
/// <summary> /// Promote target to another rank in the guild. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Promote(CharData ch, string[] str) { if( ch == null ) return; SocketConnection victimSocket; int count; bool loggedIn = false; if (ch.IsNPC()) { return; } if (str.Length == 0) { ch.SendText("Promote whom?\r\n"); return; } if (!ch.IsGuild() || ((PC)ch).GuildRank != Guild.Rank.leader) { ch.SendText("You don't have the power to do this. Only a leader may promote someone.\r\n"); return; } Guild guild = ((PC)ch).GuildMembership; CharData victim = null; foreach (CharData worldChar in Database.CharList) { if (worldChar.IsNPC()) { continue; } if (MUDString.NameContainedIn(str[0], worldChar.Name)) { victim = worldChar; loggedIn = true; break; } } if (victim == null) { if (!(CharData.LoadPlayer((victimSocket = new SocketConnection()), str[0]))) { ch.SendText("Who's that?!\r\n"); return; } victim = victimSocket.Original ? victimSocket.Original : victimSocket.Character; loggedIn = false; } if (victim.IsNPC() || victim == ch) { return; } if (!ch.IsSameGuild(victim)) { SocketConnection.Act("$N&n isn't even from $t.", ch, guild.WhoName, victim, SocketConnection.MessageTarget.character); return; } // This is technically where we would give them their guild badges. switch (((PC)victim).GuildRank) { default: return; case Guild.Rank.normal: case Guild.Rank.officer: case Guild.Rank.senior: case Guild.Rank.deputy: break; case Guild.Rank.leader: ch.SendText("You may not promote that person any further.\r\n"); return; } ((PC)victim).GuildRank++; Guild.Rank newrank = ((PC)victim).GuildRank; SetTitle(victim, guild.RankNames[(int)((PC)victim).GuildRank]); string text = String.Format("Log {0}: promoting {1} to {2} in guild {3}", ch.Name, victim.Name, newrank, ((PC)ch).GuildMembership.Name); Database.LogGuild(text); text = String.Format( "The grand Overlord {0} says:\r\n\r\nI hereby promote you {1} to {2}!'\r\n", ch.Name, victim.Name, newrank); if (loggedIn) { victim.SendText(text); } SocketConnection.Act("You have promoted $N&n to $t.", ch, newrank.ToString(), victim, SocketConnection.MessageTarget.character); for (count = 0; count < Limits.MAX_GUILD_MEMBERS; ++count) { if (!MUDString.StringsNotEqual(guild.Members[count].Name, victim.Name)) { guild.Members[count].Rank = ((PC)victim).GuildRank; } } CharData.SavePlayer(victim); guild.Save(); /* Close rented chars pfile. */ if (!loggedIn) { victimSocket = null; } return; }
/// <summary> /// Kick a character out of a guild. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void KickOut(CharData ch, string[] str) { if( ch == null ) return; SocketConnection victimSocket; bool loggedIn = false; if (str.Length == 0) { ch.SendText("Kick out whom?\r\n"); return; } if (!ch.IsGuild() || ((PC)ch).GuildRank < Guild.Rank.officer) { ch.SendText("You don't have the power to do this.\r\n"); return; } Guild guild = ((PC)ch).GuildMembership; CharData victim = null; foreach (CharData worldChar in Database.CharList) { if (worldChar.IsNPC()) { continue; } if (MUDString.NameContainedIn(str[0], worldChar.Name)) { victim = worldChar; loggedIn = true; break; } } if (victim == null) { if (!(CharData.LoadPlayer((victimSocket = new SocketConnection()), str[0]))) { ch.SendText("Who's that?!\r\n"); return; } victim = victimSocket.Original ? victimSocket.Original : victimSocket.Character; loggedIn = false; } if (victim.IsNPC()) { return; } if (victim == ch) { ch.SendText("Try &+rsociety secede&n!\r\n"); return; } if (!ch.IsSameGuild(victim)) { SocketConnection.Act("$N&n isn't even from $t.", ch, guild.WhoName, victim, SocketConnection.MessageTarget.character); return; } if (((PC)ch).GuildRank <= ((PC)victim).GuildRank) { ch.SendText("You don't have the power to do this.\r\n"); return; } string text = String.Format("Log {0}: kicking {1} from {2}", ch.Name, victim.Name, ((PC)ch).GuildMembership.Name); Database.LogGuild(text); // this _function _resets member data victim.RemoveFromGuild(); ((PC)victim).GuildRank = Guild.Rank.normal; if (loggedIn) { victim.SendText("&+RYou have been booted from your guild!&n\r\n"); } ch.SendText("You have kicked them out of the guild.\r\n"); CharData.SavePlayer(victim); guild.Save(); /* Close rented chars pfile. */ if (!loggedIn) { victimSocket = null; } return; }
/// <summary> /// Show a character to another character. /// </summary> /// <param name="victim"></param> /// <param name="ch"></param> public static void ShowCharacterToCharacterFull(CharData victim, CharData ch) { Object obj; string text = String.Empty; int percent; if (CharData.CanSee(victim, ch)) { SocketConnection.Act("$n&n looks at you.", ch, null, victim, SocketConnection.MessageTarget.victim); if (victim != ch) { SocketConnection.Act("$n&n looks at $N&n.", ch, null, victim, SocketConnection.MessageTarget.everyone_but_victim); } else { SocketConnection.Act("$n&n looks at $mself.", ch, null, victim, SocketConnection.MessageTarget.everyone_but_victim); } } if (victim.Riding != null) { text += String.Format("&nMounted on {0}, ", victim.Riding.ShowNameTo(ch, false)); } else if (victim.Rider != null) { text += String.Format("&nRidden by {0}, ", victim.Rider.ShowNameTo(ch, false)); } if (!victim.IsNPC() && victim.IsGuild()) { text += String.Format("&n{0} of {1}.\r\n", ((PC)victim).GuildRank.ToString().ToUpper(), ((PC)victim).GuildMembership.Name); } SocketConnection.Act(text, ch, null, victim, SocketConnection.MessageTarget.character); if (!String.IsNullOrEmpty(victim.Description)) { ch.SendText(victim.Description); } else { SocketConnection.Act("&nYou see nothing special about $M.", ch, null, victim, SocketConnection.MessageTarget.character); } if (victim.GetMaxHit() > 0) { percent = (100 * victim.Hitpoints) / victim.GetMaxHit(); } else { percent = -1; } text = victim.ShowNameTo(ch, true); if (percent >= 100) text += " &nis in perfect &n&+ghealth&n. "; else if (percent >= 90) text += " &nis slightly &n&+yscratched&n. "; else if (percent >= 80) text += " &nhas a &+yfew bruises&n. "; else if (percent >= 70) text += " &nhas &+Ysome cuts&n. "; else if (percent >= 60) text += " &nhas &+Mseveral wounds&n. "; else if (percent >= 50) text += " &nhas &+mmany nasty wounds&n. "; else if (percent >= 40) text += " &nis &+Rbleeding freely&n. "; else if (percent >= 30) text += " &nis &+Rcovered in blood&n. "; else if (percent >= 20) text += " &nis &+rleaking guts&n. "; else if (percent >= 10) text += " &nis &+ralmost dead&n. "; else text += " &nis &+rDYING&n. "; ch.SendText(text); // Show size on look at someone. text = MUDString.CapitalizeANSIString(String.Format("{0}&n is a {1} of {2} size.\r\n", victim.GetSexPronoun(), Race.RaceList[victim.GetRace()].ColorName, Race.SizeString(victim.CurrentSize))); ch.SendText(text); ShowAffectLines(ch, victim); bool found = false; foreach (ObjTemplate.WearLocation location in ObjTemplate.TopDownEquipment) { obj = Object.GetEquipmentOnCharacter(victim, location); if (obj && CharData.CanSeeObj(ch, obj)) { if (!found) { ch.SendText("\r\n"); SocketConnection.Act("&n$E is using:", ch, null, victim, SocketConnection.MessageTarget.character); found = true; } if (obj.ItemType == ObjTemplate.ObjectType.weapon && (location == ObjTemplate.WearLocation.hand_one || location == ObjTemplate.WearLocation.hand_three || location == ObjTemplate.WearLocation.hand_four || location == ObjTemplate.WearLocation.hand_two) && obj.HasWearFlag(ObjTemplate.WEARABLE_WIELD)) { if (obj.HasFlag(ObjTemplate.ITEM_TWOHANDED) && !ch.HasInnate(Race.RACE_EXTRA_STRONG_WIELD)) { ch.SendText("&+y(wielding twohanded) &n"); } else { ch.SendText("&+y(wielding) &n"); } } else { if (obj.ItemType == ObjTemplate.ObjectType.shield && (location == ObjTemplate.WearLocation.hand_one || location == ObjTemplate.WearLocation.hand_three || location == ObjTemplate.WearLocation.hand_four || location == ObjTemplate.WearLocation.hand_two) && obj.HasWearFlag(ObjTemplate.WEARABLE_SHIELD)) { ch.SendText("&+y(worn as shield) &n"); } else { ch.SendText(StringConversion.EquipmentLocationDisplay[(int)location]); } } ch.SendText(FormatObjectToCharacter(obj, ch, true)); ch.SendText("\r\n"); } } // Keep in mind that players can spam looking at someone in order // to increase their skill in peek - this will need to be fixed. if ((victim != ch && !ch.IsNPC() && ((((PC)ch).SkillAptitude.ContainsKey("peek") && MUDMath.NumberPercent() < ((PC)ch).SkillAptitude["peek"]) || ch.Level >= Limits.LEVEL_AVATAR)) || ch.Riding == victim || ch.Rider == victim) { ch.SendText("\r\n&nYou peek at the inventory:\r\n"); ch.PracticeSkill("peek"); ShowListToCharacter(victim.Carrying, ch, true, true); } return; }
public static void Hometown(CharData ch, string[] str) { if( ch == null ) return; if (ch == null) { Log.Error("Command.Hometown: No ch!", 0); return; } if (!ch.IsGuild() && !ch.IsImmortal()) { ch.SendText("You don't have the power to do this.\r\n"); return; } if (ch.IsNPC()) return; if (!ch.InRoom.HasFlag(RoomTemplate.ROOM_GUILDROOM)) { ch.SendText("You can't set your hometown here!\r\n"); return; } if (ch.CurrentPosition == Position.fighting || ch.Fighting) { ch.SendText("No way! You are fighting.\r\n"); return; } if (ch.CurrentPosition < Position.stunned) { ch.SendText("You're not &+RD&n&+rE&+RA&n&+rD&n yet.\r\n"); return; } string logBuf = String.Format("{0} is resetting their hometown to {1}.", ch.Name, ch.InRoom.IndexNumber); Log.Trace(logBuf); ImmortalChat.SendImmortalChat(ch, ImmortalChat.IMMTALK_LOGINS, ch.GetTrust(), logBuf); // I can't see any reason why ch would not have an .in_room, but that // may just be shortsighted of me - Xangis if (!ch.InRoom) { Log.Error("Commandhometown: ch not in a room!", 0); return; } // Put them in the correct body if (ch.Socket && ch.Socket.Original) { CommandType.Interpret(ch, "return"); } ch.SendText("You Reset your hometown.\r\n"); ((PC)ch).CurrentHome = ch.InRoom.IndexNumber; CharData.SavePlayer(ch); return; }
public static void Initiate(CharData ch, string[] str) { if( ch == null ) return; Object ring; bool found = false; int count; if (str.Length == 0) { ch.SendText("Initiate whom?\r\n"); return; } CharData victim = ch.GetCharRoom(str[0]); if (victim == null) { ch.SendText("They aren't here.\r\n"); return; } if (victim.IsNPC()) { ch.SendText("Very funny trying to enroll an NPC.\r\n"); return; } if (!ch.IsGuild() || ((PC)ch).GuildRank < Guild.Rank.officer) { ch.SendText("You don't have the power to do this.\r\n"); return; } Guild guild = ((PC)ch).GuildMembership; if (victim == ch) { return; } if (guild.Applicant != victim) { ch.SendText("They have not applied for membership to your guild.\r\n"); return; } if (victim.IsGuild()) { ch.SendText("They are already in another guild.\r\n"); return; } if (guild.NumMembers >= 30) { ch.SendText("Your guild is full.\r\n"); return; } for (count = 0; count < Limits.MAX_GUILD_MEMBERS; ++count) { if (guild.Members[count].Filled == false) { found = true; break; } } if (!found) { ch.SendText("There are no more openings in your organization.\r\n"); return; } /* if( ((PC)victim).rank == Rank.exiled ) { ch.SendText( "They are an exile and may not be guilded.\r\n" ); victim.SendText( "You are an exile and cannot be accepted into a guild.\r\n" ); return; } */ if (victim.Level < 25) { if (guild.TypeOfGuild == Guild.GuildType.clan && ch.Level >= 15) { } else if (guild.TypeOfGuild == Guild.GuildType.guild && ch.Level >= 20) { } else { SocketConnection.Act("$N&n is too low level to be initiated.", ch, null, victim, SocketConnection.MessageTarget.character); SocketConnection.Act("You are too weak to be initiated to $t!", ch, guild.WhoName, victim, SocketConnection.MessageTarget.victim); return; } } if (guild.TypeOfGuild == Guild.GuildType.guild && guild.ClassRestriction != victim.CharacterClass) ch.SendText("You may only initiate those of your class into a guild.\r\n"); ((PC)victim).GuildMembership = guild; ((PC)victim).GuildRank = Guild.Rank.normal; guild.NumMembers++; SetTitle(victim, guild.RankNames[(int)((PC)victim).GuildRank]); guild.Members[count].Name = victim.Name; guild.Members[count].Rank = ((PC)victim).GuildRank; guild.Members[count].JoinTime = Database.SystemData.CurrentTime; guild.Members[count].Filled = true; // Reset so others can apply guild.Applicant = null; if (Database.GetObjTemplate(guild.GuildRingIndexNumber)) { ring = Database.CreateObject(Database.GetObjTemplate(guild.GuildRingIndexNumber), victim.Level); if (ring) { ring.ObjToChar(victim); } } string buf = String.Format("Log {0}: initiated {1} to {2}", ch.Name, victim.Name, guild.Name); Database.LogGuild(buf); buf = String.Format("'I {0} {1}, hereby declare you {2} a member of {3}!'\r\n" + "Forever remember our motto: \"{4}\"\r\n", ((PC)ch).GuildRank, ch.Name, victim.Name, guild.WhoName, guild.Motto); victim.SendText(buf); SocketConnection.Act("$N&n has been initiated to $t!", ch, guild.WhoName, victim, SocketConnection.MessageTarget.room); SocketConnection.Act("You have initiated $N&n to $t!", ch, guild.WhoName, victim, SocketConnection.MessageTarget.character); CharData.SavePlayer(victim); guild.Save(); return; }
/// <summary> /// Inflicts damage from a spell, based on the weapon damage() function, but customized for spells. /// /// Needs to be cleaned up because it's just too big (600+ lines). /// </summary> /// <param name="ch"></param> /// <param name="victim"></param> /// <param name="dam"></param> /// <param name="spell"></param> /// <param name="damType"></param> /// <returns></returns> public static bool InflictSpellDamage( CharData ch, CharData victim, int dam, Spell spell, AttackType.DamageType damType ) { if( ch == null || victim == null || victim.CurrentPosition == Position.dead ) return true; // Remove memorization and meditation bits. // And invis. ch.BreakInvisibility(); victim.BreakMeditate(); victim.BreakMemorization(); if( CheckShrug( ch, victim ) ) return false; if( victim.CurrentPosition == Position.sleeping && !( victim.GetRace() == Race.RACE_FIRE_ELE && damType == AttackType.DamageType.fire ) && !( victim.GetRace() == Race.RACE_WATER_ELE && damType == AttackType.DamageType.water ) && !( victim.GetRace() == Race.RACE_EARTH_ELE && damType == AttackType.DamageType.earth ) && !( victim.GetRace() == Race.RACE_AIR_ELE && damType == AttackType.DamageType.wind ) ) { SocketConnection.Act( "$n&n has a rude awakening!", victim, null, null, SocketConnection.MessageTarget.room ); victim.CurrentPosition = Position.resting; if( ch.InRoom == victim.InRoom && ch.FlightLevel == victim.FlightLevel ) SetFighting( victim, ch ); } // Check for globe spells. See also FinishSpell under TargetType.singleCharacterOffensive // This check here is just to prevent area effect spells from // doing damage if too low level. The check for direct spells is in // Magic.cs if (victim.IsAffected( Affect.AFFECT_MAJOR_GLOBE) && (spell.SpellCircle[(int)ch.CharacterClass.ClassNumber] <= 6 || spell.Name == "fireshield" || spell.Name == "shockshield" || spell.Name == "soulshield" || spell.Name == "coldshield" ) ) { SocketConnection.Act( "&+RThe globe around $N&+R's body bears the brunt of your assault!&n", ch, null, victim, SocketConnection.MessageTarget.character ); SocketConnection.Act( "&+RYour globe deflects $n&+R's attack!&n", ch, null, victim, SocketConnection.MessageTarget.victim ); SocketConnection.Act( "&+R$N&+R's globe deflects $n&+R's attack!&n", ch, null, victim, SocketConnection.MessageTarget.room_vict ); return false; } if (victim.IsAffected( Affect.AFFECT_GREATER_SPIRIT_WARD) && spell.SpellCircle[(int)ch.CharacterClass.ClassNumber] <= 5) { SocketConnection.Act( "&+WThe aura around $N&+W's body bears the brunt of your assault!&n", ch, null, victim, SocketConnection.MessageTarget.character ); SocketConnection.Act( "&+WYour globe absorbs $n&+W's attack!&n", ch, null, victim, SocketConnection.MessageTarget.victim ); SocketConnection.Act( "&+W$N&+W's aura absorbs $n&+W's attack!&n", ch, null, victim, SocketConnection.MessageTarget.room_vict ); return false; } if (victim.IsAffected( Affect.AFFECT_MINOR_GLOBE) && spell.SpellCircle[(int)ch.CharacterClass.ClassNumber] <= 4) { SocketConnection.Act( "&+RThe globe around $N&+R's body bears the brunt of your assault!&n", ch, null, victim, SocketConnection.MessageTarget.character ); SocketConnection.Act( "&+RYour globe deflects $n&+R's attack!&n", ch, null, victim, SocketConnection.MessageTarget.victim ); SocketConnection.Act( "&+R$N&+R's globe deflects $n&+R's attack!&n", ch, null, victim, SocketConnection.MessageTarget.room_vict ); return false; } if (victim.IsAffected( Affect.AFFECT_SPIRIT_WARD) && spell.SpellCircle[(int)ch.CharacterClass.ClassNumber] <= 3) { SocketConnection.Act( "&+WThe aura around $N&+W's body bears the brunt of your assault!&n", ch, null, victim, SocketConnection.MessageTarget.character ); SocketConnection.Act( "&+WYour globe absorbs $n&+W's attack!&n", ch, null, victim, SocketConnection.MessageTarget.victim ); SocketConnection.Act( "&+W$N&+W's aura absorbs $n&+W's attack!&n", ch, null, victim, SocketConnection.MessageTarget.victim ); return false; } /* * Stop up any residual loopholes. */ // 1275 is average damage from Akiaurn's Power Word // I changed this to reflect that. if( ( dam > 1275 ) && ch.Level < Limits.LEVEL_AVATAR && ch.GetRace() != Race.RACE_DRAGON ) { string buf3; if( ch.IsNPC() && ch.Socket ) buf3 = String.Format( "Spell_Damage: {0} from {1} by {2}: > 1275 points with {3} spell!", dam, ch.Name, ch.Socket.Original.Name, spell.Name ); else buf3 = String.Format( "Spell_Damage: {0} from {1}: > 1275 points with {2} spell!", dam, ch.IsNPC() ? ch.ShortDescription : ch.Name, spell.Name ); Log.Error( buf3, 0 ); dam = 1275; } if (victim.IsAffected( Affect.AFFECT_MINOR_PARA) && !( victim.GetRace() == Race.RACE_FIRE_ELE && damType == AttackType.DamageType.fire ) && !( victim.GetRace() == Race.RACE_WATER_ELE && damType == AttackType.DamageType.water ) && !( victim.GetRace() == Race.RACE_EARTH_ELE && damType == AttackType.DamageType.earth ) && !( victim.GetRace() == Race.RACE_AIR_ELE && damType == AttackType.DamageType.wind ) ) { SocketConnection.Act( "$n&n disrupts the magic preventing $N&n from moving.", ch, null, victim, SocketConnection.MessageTarget.room_vict ); SocketConnection.Act( "You disrupt the magic preventing $N&n from moving.", ch, null, victim, SocketConnection.MessageTarget.character ); SocketConnection.Act( "&+YYou can move again.&n", ch, null, victim, SocketConnection.MessageTarget.victim ); victim.RemoveAffect( Affect.AFFECT_MINOR_PARA ); victim.AffectStrip( Affect.AffectType.spell, "earthen grasp" ); victim.AffectStrip( Affect.AffectType.spell, "greater earthen grasp"); } bool immune = false; if( victim != ch ) { /* * Certain attacks are forbidden. * Most other attacks are returned. */ if( IsSafe( ch, victim ) ) return false; // is_safe could wipe out victim, as it calls procs if a boss // check and see that victim is still valid if( !victim ) return true; Crime.CheckAttemptedMurder( ch, victim ); if( victim.CurrentPosition > Position.stunned && !( victim.GetRace() == Race.RACE_FIRE_ELE && damType == AttackType.DamageType.fire ) && !( victim.GetRace() == Race.RACE_WATER_ELE && damType == AttackType.DamageType.water ) && !( victim.GetRace() == Race.RACE_EARTH_ELE && damType == AttackType.DamageType.earth ) && !( victim.GetRace() == Race.RACE_AIR_ELE && damType == AttackType.DamageType.wind ) ) { // Offensive spells engage victim if not fighting, and // caster only if neither are fighting. if( !victim.Fighting && victim.InRoom == ch.InRoom && victim.FlightLevel == ch.FlightLevel ) { SetFighting( victim, ch ); if( !ch.Fighting ) SetFighting( ch, victim ); // Can't have prone people automaticaly stand. if( victim.CurrentPosition == Position.standing ) victim.CurrentPosition = Position.fighting; } /* * If NPC victim is following, ch might attack victim's master. * No charm check here because charm would be dispelled from * tanking mobile when combat ensues thus ensuring PC charmer is * not harmed. * Check for is_same_group wont work as following mobile is not * always grouped with PC charmer */ if( ch.IsNPC() && victim.IsNPC() && victim.Master && victim.Master.InRoom == ch.InRoom && MUDMath.NumberBits( 2 ) == 0 ) { StopFighting( ch, false ); SetFighting( ch, victim.Master ); return false; } } /* * More charm stuff. */ if( victim.Master == ch && !( victim.GetRace() == Race.RACE_FIRE_ELE && damType == AttackType.DamageType.fire ) && !( victim.GetRace() == Race.RACE_WATER_ELE && damType == AttackType.DamageType.water ) && !( victim.GetRace() == Race.RACE_EARTH_ELE && damType == AttackType.DamageType.earth ) && !( victim.GetRace() == Race.RACE_AIR_ELE && damType == AttackType.DamageType.wind ) ) StopFighting( victim, true ); /* * Hunting stuff... */ if( dam != 0 && victim.IsNPC() && !( victim.GetRace() == Race.RACE_FIRE_ELE && damType == AttackType.DamageType.fire ) && !( victim.GetRace() == Race.RACE_WATER_ELE && damType == AttackType.DamageType.water ) && !( victim.GetRace() == Race.RACE_EARTH_ELE && damType == AttackType.DamageType.earth ) && !( victim.GetRace() == Race.RACE_AIR_ELE && damType == AttackType.DamageType.wind ) ) { StartGrudge( victim, ch, false ); } /* * Damage modifiers. */ if (victim.IsAffected( Affect.AFFECT_SANCTUARY)) dam /= 2; if ((victim.IsAffected( Affect.AFFECT_PROTECT_EVIL)) && ch.IsEvil()) dam -= dam / 8; else if ((victim.IsAffected( Affect.AFFECT_PROTECT_GOOD)) && ch.IsGood()) dam -= dam / 8; if( dam < 0 ) dam = 0; } switch( victim.CheckRIS( damType ) ) { case Race.ResistanceType.resistant: dam -= dam / 3; break; case Race.ResistanceType.immune: immune = true; dam = 0; break; case Race.ResistanceType.susceptible: dam += dam / 2; break; case Race.ResistanceType.vulnerable: dam *= 2; break; } if( ( damType == AttackType.DamageType.wind || damType == AttackType.DamageType.gas || damType == AttackType.DamageType.asphyxiation ) && victim.IsAffected( Affect.AFFECT_DENY_AIR)) { if( MUDMath.NumberPercent() < 50 ) { victim.SendText( "&+CYou deny the damage.&n\r\n" ); immune = true; dam = 0; } else dam -= dam / 5; } if (damType == AttackType.DamageType.fire && victim.IsAffected( Affect.AFFECT_DENY_FIRE)) { if( MUDMath.NumberPercent() < 50 ) { victim.SendText( "&+rYou deny the damage.&n\r\n" ); immune = true; dam = 0; } else dam -= dam / 5; } if( ( damType == AttackType.DamageType.earth || damType == AttackType.DamageType.crushing ) && victim.IsAffected(Affect.AFFECT_DENY_EARTH)) { if( MUDMath.NumberPercent() < 50 ) { victim.SendText( "&+yYou deny the damage.&n\r\n" ); immune = true; dam = 0; } else dam -= dam / 5; } if( ( damType == AttackType.DamageType.water || damType == AttackType.DamageType.acid || damType == AttackType.DamageType.drowning ) && victim.IsAffected(Affect.AFFECT_DENY_WATER)) { if( MUDMath.NumberPercent() < 50 ) { victim.SendText( "&+bYou deny the damage.&n\r\n" ); immune = true; dam = 0; } else dam -= dam / 5; } // Check for protection spells that give 25% damage reduction - Xangis if (damType == AttackType.DamageType.fire && victim.IsAffected( Affect.AFFECT_PROTECT_FIRE)) dam = ( dam * 3 ) / 4; else if (damType == AttackType.DamageType.cold && victim.IsAffected( Affect.AFFECT_PROTECT_COLD)) dam = ( dam * 3 ) / 4; else if (damType == AttackType.DamageType.acid && victim.IsAffected( Affect.AFFECT_PROTECT_ACID)) dam = ( dam * 3 ) / 4; else if (damType == AttackType.DamageType.gas && victim.IsAffected( Affect.AFFECT_PROTECT_GAS)) dam = ( dam * 3 ) / 4; else if (damType == AttackType.DamageType.electricity && victim.IsAffected( Affect.AFFECT_PROTECT_LIGHTNING)) dam = ( dam * 3 ) / 4; /* * We moved DamageMessage out of the victim != ch if above * so self damage would show. Other valid type_undefined * damage is ok to avoid like mortally wounded damage */ if( spell != Spell.SpellList["reserved"] && !( victim.GetRace() == Race.RACE_FIRE_ELE && damType == AttackType.DamageType.fire ) && !( victim.GetRace() == Race.RACE_WATER_ELE && damType == AttackType.DamageType.water ) && !( victim.GetRace() == Race.RACE_EARTH_ELE && damType == AttackType.DamageType.earth ) && !( victim.GetRace() == Race.RACE_AIR_ELE && damType == AttackType.DamageType.wind ) ) SendSpellDamageMessage( ch, victim, dam, spell, immune ); /* PC to PC damage quartered. * NPC to PC damage divided by 3. */ if( dam > 0 && !victim.IsNPC() && victim != ch ) { if( !ch.IsNPC() ) dam /= 4; else dam /= 3; } /* * Hurt the victim. * Inform the victim of his new state. */ if( !( victim.GetRace() == Race.RACE_FIRE_ELE && damType == AttackType.DamageType.fire ) && !( victim.GetRace() == Race.RACE_WATER_ELE && damType == AttackType.DamageType.water ) && !( victim.GetRace() == Race.RACE_EARTH_ELE && damType == AttackType.DamageType.earth ) && !( victim.GetRace() == Race.RACE_AIR_ELE && damType == AttackType.DamageType.wind ) ) { /* Added damage exp! */ // chance added because people level faster and faster as they get higher level... // you can now only get damage exp on mobs that con easy or better // and there's only a 25% chance per hit of you evern being eligible for damage exp. if( MUDMath.NumberPercent() < 25 && victim.Level >= ( ch.Level - 3 ) ) ch.GainExperience( Math.Max( 1, dam / 20 ) ); victim.Hitpoints -= dam; } else { string attack; if( spell != null && spell != Spell.SpellList["none"] ) attack = spell.Name; else attack = "it"; SocketConnection.Act( "$N&n absorbs your $t!", ch, attack, victim, SocketConnection.MessageTarget.character ); SocketConnection.Act( "You absorb $n&n's $t!", ch, attack, victim, SocketConnection.MessageTarget.victim ); SocketConnection.Act( "$N&n absorbs $n&n's $t", ch, attack, victim, SocketConnection.MessageTarget.room_vict ); if( ch.IsImmortal() ) { string buf4 = String.Format( "You healed {0} damage.", victim.GetMaxHit() >= dam + victim.Hitpoints ? dam : victim.GetMaxHit() - victim.Hitpoints ); ch.SendText( buf4 ); } victim.Hitpoints = Math.Min( victim.GetMaxHit(), victim.Hitpoints + dam ); return false; } if( !victim.IsNPC() && victim.Level >= Limits.LEVEL_AVATAR && victim.Hitpoints < 1 ) victim.Hitpoints = 1; if (victim.IsAffected(Affect.AFFECT_BERZERK) && victim.CurrentPosition <= Position.stunned ) victim.RemoveAffect(Affect.AFFECT_BERZERK); victim.UpdatePosition(); switch( victim.CurrentPosition ) { case Position.mortally_wounded: victim.SendText( "&+LYou are &+Rmo&n&+rr&+Rt&n&+ral&+Rl&n&+ry&+L wounded, and will die soon, if not aided.&n\r\n" ); SocketConnection.Act( "$n&+L is &+Rmo&n&+rr&+Rt&n&+ral&+Rl&n&+ry&+L wounded, and will die soon, if not aided.&n", victim, null, null, SocketConnection.MessageTarget.room, true ); StopNotVicious( victim ); break; case Position.incapacitated: victim.SendText( "&+LYou are incapacitated and will slowly &n&+rbl&+Re&n&+re&+Rd&+L to death, if not aided.\r\n" ); SocketConnection.Act( "$n&+L is incapacitated and will slowly &n&+rbl&+Re&n&+re&+Rd&+L to death, if not aided.&n", victim, null, null, SocketConnection.MessageTarget.room, true ); StopNotVicious( victim ); break; case Position.stunned: victim.SendText( "&+LYou are stunned, but will probably recover.&n\r\n" ); SocketConnection.Act( "$n&+L is stunned, but will probably recover.&n", victim, null, null, SocketConnection.MessageTarget.room, true ); break; case Position.dead: SocketConnection.Act( spell.MessageKill, ch, null, victim, SocketConnection.MessageTarget.room_vict ); SocketConnection.Act( spell.MessageKill, ch, null, victim, SocketConnection.MessageTarget.character ); if( victim == ch ) { victim.SendText( "&+LYou have been &+Rsl&n&+ra&+Ri&n&+rn&+L!&n\r\n\r\n" ); } else { string buf = String.Format( "&+LYou have been &+Rsl&n&+ra&+Ri&n&+rn&+L by&n {0}&+L!&n\r\n\r\n", ch.ShowNameTo( victim, false ) ); victim.SendText( buf ); } StopFighting( victim, true ); SocketConnection.Act( "$n&+L is &n&+rdead&+L!&n", victim, null, null, SocketConnection.MessageTarget.room, true ); break; default: if( dam > victim.GetMaxHit() / 5 ) victim.SendText( "That really did &+RHURT&n!\r\n" ); if( victim.Hitpoints < victim.GetMaxHit() / 10 ) victim.SendText( "You sure are &n&+rBL&+RE&n&+rE&+RDI&n&+rN&+RG&n!\r\n" ); break; } /* * Sleep spells and extremely wounded folks. */ if( !victim.IsAwake() ) /* lets make NPC's not slaughter PC's */ { if( victim.Fighting && victim.Fighting.Hunting && victim.Fighting.Hunting.Who == victim ) StopHunting( victim.Fighting ); if( victim.Fighting && !victim.IsNPC() && ch.IsNPC() ) StopFighting( victim, true ); else StopFighting( victim, false ); } /* * Payoff for killing things. */ if( victim.CurrentPosition == Position.dead ) { StopFighting( ch, false ); if( !victim.HasActionBit(MobTemplate.ACT_NOEXP ) || !victim.IsNPC() ) GroupExperienceGain( ch, victim ); if( !victim.IsNPC() ) { if( ch.IsNPC() ) { ( (PC)victim ).MobDeaths++; if( victim.IsGuild() ) { ( (PC)victim ).GuildMembership.MonsterDeaths++; ( (PC)victim ).GuildMembership.Score += CalculateDeathScore( ch, victim ); } ( (PC)victim ).Score += CalculateDeathScore( ch, victim ); } else { ( (PC)ch ).PlayerKills++; ( (PC)victim ).PlayerDeaths++; ( (PC)victim ).Score += CalculateDeathScore( ch, victim ); ( (PC)ch ).Score += CalculateKillScore( ch, victim ); if( ch.IsGuild() && victim.IsGuild() && ( (PC)ch ).GuildMembership != ( (PC)victim ).GuildMembership ) { ( (PC)ch ).GuildMembership.PlayerKills++; ( (PC)victim ).GuildMembership.PlayerDeaths++; ( (PC)ch ).GuildMembership.Score += CalculateKillScore( ch, victim ); ( (PC)victim ).GuildMembership.Score += CalculateDeathScore( ch, victim ); } } string logBuf = String.Format( "{0}&n killed by {1}&n at {2}", victim.Name, ( ch.IsNPC() ? ch.ShortDescription : ch.Name ), victim.InRoom.IndexNumber ); Log.Trace( logBuf ); ImmortalChat.SendImmortalChat( ch, ImmortalChat.IMMTALK_DEATHS, Limits.LEVEL_AVATAR, logBuf ); /* * Dying penalty: * 1/2 way back to previous 2 levels. */ // Newbies do not lose exp from death. if( ch.Level > 5 ) victim.GainExperience( ( 0 - ( ( ( 50 + victim.Level ) * ExperienceTable.Table[ victim.Level ].LevelExperience ) / 400 ) ) ); if( victim.Level < 2 && victim.ExperiencePoints < 1 ) victim.ExperiencePoints = 1; } else { if( !ch.IsNPC() ) { ( (PC)ch ).MobKills++; if( ch.IsGuild() ) { ( (PC)ch ).GuildMembership.MonsterKills++; ( (PC)ch ).GuildMembership.Score += CalculateKillScore( ch, victim ); } ( (PC)ch ).Score += CalculateKillScore( ch, victim ); } } KillingBlow( ch, victim ); // Keep in mind after this point the character is not in the // CharList, not in any room, and is at the menu. Don't do // anything that would cause a segmentation fault. if( ch.IsGuild() && victim.IsGuild() && ( (PC)ch ).GuildMembership != ( (PC)victim ).GuildMembership ) { ( (PC)ch ).GuildMembership.Score += 20; } return true; } if( victim == ch ) { return false; } /* * Wimp out? */ if( victim.IsNPC() && dam > 0 ) { if( ( victim.HasActionBit(MobTemplate.ACT_WIMPY ) && MUDMath.NumberBits( 1 ) == 0 && victim.Hitpoints < victim.GetMaxHit() / 5 ) || (victim.IsAffected(Affect.AFFECT_CHARM) && victim.Master && victim.Master.InRoom != victim.InRoom ) ) { StartFearing( victim, ch ); StopHunting( victim ); CommandType.Interpret(victim, "flee"); } } if( !victim.IsNPC() && victim.Hitpoints > 0 && victim.Hitpoints <= victim.Wimpy ) { CommandType.Interpret(victim, "flee"); } return false; }
/// <summary> /// Inflict damage from a single hit. This could use some cleanup since it's way too unwieldy at more than 600 lines. /// </summary> /// <param name="ch"></param> /// <param name="victim"></param> /// <param name="dam"></param> /// <param name="skill"></param> /// <param name="weapon"></param> /// <param name="damType"></param> /// <returns></returns> public static bool InflictDamage(CharData ch, CharData victim, int dam, string skill, ObjTemplate.WearLocation weapon, AttackType.DamageType damType) { if (ch == null || victim == null) { return false; } Object obj; bool critical = false; if( victim.CurrentPosition == Position.dead || victim.Hitpoints < -10 ) { return true; } /* * Stop up any residual loopholes. */ if( ( dam > 1276 ) && ch.Level < Limits.LEVEL_AVATAR ) { string text; if (ch.IsNPC() && ch.Socket) { text = String.Format("Damage: {0} from {1} by {2}: > 1276 points with {3} damage type!", dam, ch.Name, ch.Socket.Original.Name, skill); } else { text = String.Format("Damage: {0} from {1}: > 1276 points with {2} damage type!", dam, ch.IsNPC() ? ch.ShortDescription : ch.Name, skill); } Log.Error( text, 0 ); dam = 1276; } // Remove memorization and meditation bits - Xangis victim.BreakMeditate(); victim.BreakMemorization(); if (victim.IsAffected( Affect.AFFECT_MINOR_PARA)) { SocketConnection.Act( "$n&n disrupts the magic preventing $N&n from moving.", ch, null, victim, SocketConnection.MessageTarget.room_vict ); SocketConnection.Act( "You disrupt the magic preventing $N&n from moving.", ch, null, victim, SocketConnection.MessageTarget.character ); SocketConnection.Act( "&+YYou can move again.&n", ch, null, victim, SocketConnection.MessageTarget.victim ); victim.RemoveAffect( Affect.AFFECT_MINOR_PARA ); } bool immune = false; if( victim != ch ) { /* * Certain attacks are forbidden. * Most other attacks are returned. */ victim = CheckGuarding( ch, victim ); if( IsSafe( ch, victim ) ) return false; // is_safe could wipe out victim, as it calls procs if a boss // check and see that victim is still valid if( victim == null ) return true; Crime.CheckAttemptedMurder( ch, victim ); if( victim.CurrentPosition > Position.stunned ) { if( !victim.Fighting ) SetFighting( victim, ch ); // Can't have prone people automatically stand if( victim.CurrentPosition == Position.standing ) victim.CurrentPosition = Position.fighting; if( !ch.Fighting ) SetFighting( ch, victim ); /* * If NPC victim is following, ch might attack victim's master. * No charm check here because charm would be dispelled from * tanking mobile when combat ensues thus ensuring PC charmer is * not harmed. * Check for IsSameGroup wont work as following mobile is not * always grouped with PC charmer * * Added a check for whether ch has switch skill. If not, * much lower chancing of retargetting */ if( ch.IsNPC() && victim.IsNPC() && victim.Master && victim.Master.InRoom == ch.InRoom && MUDMath.NumberBits( 2 ) == 0 ) { StartGrudge( ch, victim.Master, false ); } } /* * More charm stuff. */ if( victim.Master == ch ) { StopFighting( victim, true ); } ch.BreakInvisibility(); /* * Hunting stuff... */ if( dam != 0 && victim.IsNPC() ) { /* StartGrudge is combined StartHating and StartHunting */ StartGrudge( victim, ch, false ); } /* * Damage modifiers. */ // Critical hits for double damage // Average of 5% for those that have average luck // Gnomes could concievably have 10% if( MUDMath.NumberPercent() < ( 2 + ( ch.GetCurrLuck() / 18 ) ) && dam > 0 ) { ch.SendText( "&+WYou score a CRITICAL HIT!&n\r\n" ); dam *= 2; critical = true; } if( victim.IsAffected( Affect.AFFECT_SANCTUARY ) ) dam /= 2; if( victim.IsAffected( Affect.AFFECT_PROTECT_EVIL ) && ch.IsEvil() ) dam -= dam / 8; else if( victim.IsAffected( Affect.AFFECT_PROTECT_GOOD ) && ch.IsGood() ) dam -= dam / 8; // Check stoneskin. People not affected by a stoneskin affect // cannot lose their stoneskin for any reason. This should mean // that mobs will keep their stoneskin and players should always // have a chance to lose it, since no player should ever be // setbit stoneskin. // // The bool value of found is used so that we can have them // take full damage when their stoneskin shatters, but get the // damage reduction if they are either a mob or their stoneskin // wears off that round. // /* Yeah, yeah.. so maybe backstabs shouldn't be aff'd. */ // Actually they should be affected, but they should have a much // higher chance of getting through (say 30-70%). // // Critical hits will now go through stoneskin // automatically if (!critical && victim.IsAffected( Affect.AFFECT_STONESKIN) && ( skill != "backstab" || MUDMath.NumberPercent() < ( 25 + ch.Level ) ) ) { bool found = false; for (int i = (victim.Affected.Count - 1); i >= 0; i--) { if( victim.Affected[i].HasBitvector( Affect.AFFECT_STONESKIN ) ) { // Small chance of shattering the stoneskin on a good hit. // Reduced chance by about 20% if( dam >= 25 && MUDMath.NumberPercent() <= ( dam / 12 ) ) { victim.SendText( "&+LYour stoneskin is shattered by the massive blow!&n\r\n" ); SocketConnection.Act( "$n&n's massive blow shatters $N&n's stoneskin!", ch, null, victim, SocketConnection.MessageTarget.everyone_but_victim ); SocketConnection.Act( "Your massive blow shatters $N&n's stoneskin!", ch, null, victim, SocketConnection.MessageTarget.character ); victim.RemoveAffect(victim.Affected[i]); found = true; } else if( dam > 0 ) // Added check for actual damage { for( int j = 0; j < victim.Affected[i].Modifiers.Count; j++ ) { victim.Affected[i].Modifiers[j].Amount--; if (victim.Affected[i].Modifiers[j].Amount < 1) { victim.RemoveAffect(victim.Affected[i]); victim.SendText("&+LYou feel your skin soften and return to normal.&n\r\n"); } dam /= 15; found = true; } } } } // This means they're Affect.AFFECT_STONESKIN as an innate/permenant. // We will still allow it to shatter, but it will refresh itself // upon a mob update. Because of this, we make it easier to shatter. // No damage reduction when it shatters. if( !found ) { if( dam >= 8 && MUDMath.NumberPercent() <= ( dam / 8 ) ) { victim.SendText( "&+LYour stoneskin is shattered by the massive blow!&n\r\n" ); SocketConnection.Act( "$n&n's massive blow shatters $N&n's stoneskin!", ch, null, victim, SocketConnection.MessageTarget.everyone_but_victim ); SocketConnection.Act( "Your massive blow shatters $N&n's stoneskin!", ch, null, victim, SocketConnection.MessageTarget.character ); victim.RemoveAffect( Affect.AFFECT_STONESKIN ); } else { dam = dam / 15 != 0 ? dam / 15 : 1; } } } if( dam < 0 ) dam = 0; /* * Check for disarm, trip, parry, dodge and shield block. */ if (skill != "barehanded fighting" || skill == "kick") { // Trip and disarm removed because those should be handled // by each individual mob's special function. if( ch.IsNPC() && ch.HasInnate( Race.RACE_WEAPON_WIELD ) && MUDMath.NumberPercent() < Math.Min( 25, Math.Max( 10, ch.Level ) ) && !victim.IsNPC() ) UseMagicalItem( ch ); } } switch( victim.CheckRIS( damType ) ) { case Race.ResistanceType.resistant: dam -= dam / 3; break; case Race.ResistanceType.immune: immune = true; dam = 0; break; case Race.ResistanceType.susceptible: dam += dam / 2; break; case Race.ResistanceType.vulnerable: dam *= 2; break; default: break; } if( ( damType == AttackType.DamageType.wind || damType == AttackType.DamageType.gas || damType == AttackType.DamageType.asphyxiation ) && victim.IsAffected(Affect.AFFECT_DENY_AIR)) { if( MUDMath.NumberPercent() < 50 ) { ch.SendText( "&+CYou deny the damage.&n\r\n" ); immune = true; dam = 0; } else dam -= dam / 5; } if (damType == AttackType.DamageType.fire && victim.IsAffected( Affect.AFFECT_DENY_FIRE)) { if( MUDMath.NumberPercent() < 50 ) { ch.SendText( "&+rYou deny the damage.&n\r\n" ); immune = true; dam = 0; } else dam -= dam / 5; } if( ( damType == AttackType.DamageType.earth || damType == AttackType.DamageType.crushing ) && victim.IsAffected( Affect.AFFECT_DENY_EARTH)) { if( MUDMath.NumberPercent() < 50 ) { ch.SendText( "&+yYou deny the damage.&n\r\n" ); immune = true; dam = 0; } else dam -= dam / 5; } if( ( damType == AttackType.DamageType.water || damType == AttackType.DamageType.acid || damType == AttackType.DamageType.drowning ) && victim.IsAffected( Affect.AFFECT_DENY_WATER)) { if( MUDMath.NumberPercent() < 50 ) { ch.SendText( "&+bYou deny the damage.&n\r\n" ); immune = true; dam = 0; } else dam -= dam / 5; } // Check for protection spells that give 25% damage reduction - Xangis if (damType == AttackType.DamageType.fire && victim.IsAffected( Affect.AFFECT_PROTECT_FIRE)) dam = ( dam * 3 ) / 4; else if (damType == AttackType.DamageType.cold && victim.IsAffected( Affect.AFFECT_PROTECT_COLD)) dam = ( dam * 3 ) / 4; else if (damType == AttackType.DamageType.acid && victim.IsAffected( Affect.AFFECT_PROTECT_ACID)) dam = ( dam * 3 ) / 4; else if (damType == AttackType.DamageType.gas && victim.IsAffected( Affect.AFFECT_PROTECT_GAS)) dam = ( dam * 3 ) / 4; else if (damType == AttackType.DamageType.electricity && victim.IsAffected( Affect.AFFECT_PROTECT_LIGHTNING)) dam = ( dam * 3 ) / 4; // Barkskin protects from 8% of slash and 12% of pierce damage. if (victim.IsAffected( Affect.AFFECT_BARKSKIN)) { if (skill == "1h slashing" || skill == "2h slashing") dam = dam * 11 / 12; else if (skill == "1h piercing" || skill == "2h piercing") dam = dam * 7 / 8; } // Check for vampiric touch for anti-paladins and vampires if( weapon == ObjTemplate.WearLocation.hand_one || weapon == ObjTemplate.WearLocation.hand_two || weapon == ObjTemplate.WearLocation.hand_three || weapon == ObjTemplate.WearLocation.hand_four ) { if( ( ( ch.IsClass(CharClass.Names.antipaladin) || ch.GetRace() == Race.RACE_VAMPIRE ) && skill == "barehanded fighting" && !Object.GetEquipmentOnCharacter(ch, weapon)) || (ch.IsAffected( Affect.AFFECT_VAMP_TOUCH) && ( !( obj = Object.GetEquipmentOnCharacter( ch, weapon ) ) || obj.HasAffect( Affect.AFFECT_VAMP_TOUCH ) ) ) ) { ch.Hitpoints += dam / 3; if( ch.Hitpoints > ( ch.GetMaxHit() + 50 + ch.Level * 5 ) ) { ch.Hitpoints = ch.GetMaxHit() + 50 + ch.Level * 5; } } } /* PC to PC damage quartered. * NPC to PC damage divided by 3. */ if( dam > 0 && !victim.IsNPC() && victim != ch ) { if( !ch.IsNPC() ) dam /= 4; else dam /= 3; } /* * Just a check for anything that is excessive damage * Send a log message, keeping the imms on their toes * Changed this from 300 to 250 'cause hitters get more than one * attack/round and w/haste that's 1000 possible in the time one fist * goes off. That's more than the fist might do and it has to be * memmed. */ if (dam > 250 && skill != "backstab" ) { string buf4; if (!string.IsNullOrEmpty(skill)) { buf4 = String.Format("Excessive damage: {0} attacking {1} for {2}, skill = {3}({4}).", ch.Name, victim.Name, dam, Skill.SkillList[skill].DamageText, skill); } else { buf4 = String.Format("Excessive damage: {0} attacking {1} for {2}, unknown damage type.", ch.Name, victim.Name, dam); } Log.Trace( buf4 ); } /* * We moved DamageMessage out of the victim != ch if above * so self damage would show. Other valid type_undefined * damage is ok to avoid like mortally wounded damage */ if (!String.IsNullOrEmpty(skill)) { SendDamageMessage(ch, victim, dam, skill, weapon, immune); } victim.Hitpoints -= dam; /* Check for HOLY_SACRFICE and BATTLE_ECSTASY */ if( dam > 0 && victim != ch ) { CharData groupChar; if (victim.IsAffected( Affect.AFFECT_HOLY_SACRIFICE) && victim.GroupLeader) { for( groupChar = victim.GroupLeader; groupChar; groupChar = groupChar.NextInGroup ) { if( groupChar == victim || groupChar.InRoom != ch.InRoom ) continue; groupChar.Hitpoints += dam / 5; if (groupChar.Hitpoints > groupChar.GetMaxHit() + 50 + groupChar.Level * 5) { groupChar.Hitpoints = groupChar.GetMaxHit() + 50 + groupChar.Level * 5; } } //end for loop } //end if holy sac if( ch.GroupLeader != null ) { for( groupChar = ch.GroupLeader; groupChar != null; groupChar = groupChar.NextInGroup ) { if( groupChar == victim || groupChar.InRoom != ch.InRoom ) continue; if( groupChar.IsAffected( Affect.AFFECT_BATTLE_ECSTASY ) ) { groupChar.Hitpoints += dam / 20; if( groupChar.Hitpoints > groupChar.GetMaxHit() + 50 + groupChar.Level * 5 ) groupChar.Hitpoints = groupChar.GetMaxHit() + 50 + groupChar.Level * 5; } // end if battle ecstasy } //end for loop } //end if grouped } //end if // Make sure if they got an instant kill roll that the victim dies. if (skill == "instant kill") { if( victim.GetRace() != Race.RACE_DEVIL && victim.GetRace() != Race.RACE_DEMON && victim.GetRace() != Race.RACE_GOD ) victim.Hitpoints = -20; } /* Added damage exp! */ // chance added because people level faster and faster as they get higher level... // to be worked out when exp is redone. // you can now only get damage exp on mobs that con easy or better // and there's only a 25% chance per hit of you evern being eligible for damage exp. if( MUDMath.NumberPercent() < 25 && victim.Level >= ( ch.Level - 3 ) ) ch.GainExperience( Math.Max( 1, dam / 20 ) ); if( !victim.IsNPC() && victim.Level >= Limits.LEVEL_AVATAR && victim.Hitpoints < 1 ) victim.Hitpoints = 1; /* * Magic shields that retaliate * * Apparently two people with the same sort of shield do not * take damage from each other */ if( ( dam > 1 ) && victim != ch ) { if( victim.IsAffected( Affect.AFFECT_FIRESHIELD ) && !ch.IsAffected( Affect.AFFECT_FIRESHIELD ) ) InflictSpellDamage( victim, ch, dam / 2, "fireshield", AttackType.DamageType.fire ); if (victim.IsAffected( Affect.AFFECT_COLDSHIELD) && !ch.IsAffected(Affect.AFFECT_COLDSHIELD)) InflictSpellDamage( victim, ch, dam / 2, "coldshield", AttackType.DamageType.cold ); if (victim.IsAffected(Affect.AFFECT_SHOCK_SHIELD) && !ch.IsAffected(Affect.AFFECT_SHOCK_SHIELD)) InflictSpellDamage( victim, ch, dam / 2, "shockshield", AttackType.DamageType.electricity ); /* Soulshield is a complex one. If the attacker and victim are of * opposite alignment, the shield retaliates with 1/2 damage just like * any other shield. If the victim is neutral and the attacker is * not, the shield retaliates with 1/4 damage. If the victim is good * or evil and the attacker is neutral, the shield retaliates with * 1/8 damage. If the attacker and victim are of same alignment, * the shield does nothing. */ if (victim.IsAffected(Affect.AFFECT_SOULSHIELD) && !ch.IsAffected(Affect.AFFECT_SOULSHIELD)) { if( victim.IsEvil() && ch.IsGood() ) InflictSpellDamage(victim, ch, dam / 2, "soulshield", AttackType.DamageType.harm); else if( victim.IsGood() && ch.IsEvil() ) InflictSpellDamage(victim, ch, dam / 2, "soulshield", AttackType.DamageType.harm); else if( victim.IsNeutral() && ( ch.IsEvil() || ch.IsGood() ) ) InflictSpellDamage(victim, ch, dam / 4, "soulshield", AttackType.DamageType.harm); else if( victim.IsGood() && ch.IsNeutral() ) InflictSpellDamage(victim, ch, dam / 8, "soulshield", AttackType.DamageType.harm); else if( victim.IsEvil() && ch.IsNeutral() ) InflictSpellDamage(victim, ch, dam / 8, "soulshield", AttackType.DamageType.harm); } } if (victim.IsAffected( Affect.AFFECT_BERZERK ) && victim.CurrentPosition <= Position.stunned ) victim.RemoveAffect(Affect.AFFECT_BERZERK); if (dam > 0 && skill != "barehanded fighting" && IsWieldingPoisoned( ch, weapon ) && !Magic.SpellSavingThrow( ch.Level, victim, AttackType.DamageType.poison ) ) { InflictPoison( "poison_weapon", ch.Level, IsWieldingPoisoned( ch, weapon ), ch, victim ); SocketConnection.Act( "$n&n suffers from the &+Gpoison&n inflicted upon $m.", victim, null, null, SocketConnection.MessageTarget.room, true ); Object.StripAffect( Object.GetEquipmentOnCharacter( ch, weapon ), Affect.AffectType.skill, "poison weapon" ); } victim.UpdatePosition(); switch( victim.CurrentPosition ) { case Position.mortally_wounded: victim.SendText( "&+LYou are &+Rmo&n&+rr&+Rt&n&+ral&+Rl&n&+ry&+L wounded, and will die soon, if not aided.&n\r\n" ); SocketConnection.Act( "$n&+L is &+Rmo&n&+rr&+Rt&n&+ral&+Rl&n&+ry&+L wounded, and will die soon, if not aided.&n", victim, null, null, SocketConnection.MessageTarget.room, true ); StopNotVicious( victim ); break; case Position.incapacitated: victim.SendText( "&+LYou are incapacitated and will &n&+rbl&+Re&n&+re&+Rd&+L to death, if not aided.&n\r\n" ); SocketConnection.Act( "$n&+L is incapacitated and will slowly &n&+rbl&+Re&n&+re&+Rd&+L to death, if not aided.&n", victim, null, null, SocketConnection.MessageTarget.room, true ); StopNotVicious( victim ); break; case Position.stunned: victim.SendText( "&+LYou are stunned, but will probably recover.&n\r\n" ); SocketConnection.Act( "$n&+L is stunned, but will probably recover.&n", victim, null, null, SocketConnection.MessageTarget.room, true ); break; case Position.dead: if( victim == ch ) { victim.SendText( "&+LYou have been &+Rsl&n&+ra&+Ri&n&+rn&+L!&n\r\n\r\n" ); } else { string buf = String.Format( "&+LYou have been &+Rsl&n&+ra&+Ri&n&+rn&+L by&n {0}&+L!&n\r\n\r\n", ch.ShowNameTo( victim, false ) ); victim.SendText( buf ); } /* Added this to stop a bug. */ Combat.StopFighting( victim, true ); SocketConnection.Act( "$n&+L is &n&+rdead&+L!&n", victim, null, null, SocketConnection.MessageTarget.room, true ); break; default: if( dam > victim.GetMaxHit() / 5 ) victim.SendText( "That really did &+RHURT&n!\r\n" ); if( victim.Hitpoints < victim.GetMaxHit() / 10 ) victim.SendText( "You sure are &n&+rBL&+RE&n&+rE&+RDI&n&+rN&+RG&n!\r\n" ); break; } // Check for weapon procs if( ( obj = Object.GetEquipmentOnCharacter( ch, weapon ) ) && Position.dead != victim.CurrentPosition ) { if( obj.SpecFun.Count > 0 ) obj.CheckSpecialFunction(true); } /* * Sleep spells and extremely wounded folks. */ if( !victim.IsAwake() ) /* lets make NPC's not slaughter PC's */ { if( victim.Fighting && victim.Fighting.Hunting && victim.Fighting.Hunting.Who == victim ) StopHunting( victim.Fighting ); if( victim.Fighting && !victim.IsNPC() && ch.IsNPC() ) StopFighting( victim, true ); else StopFighting( victim, false ); } /* * Payoff for killing things. */ if( victim.CurrentPosition == Position.dead ) { // Done in attempt to squelch the combat continuation bug StopFighting( victim, true ); if( !victim.HasActionBit(MobTemplate.ACT_NOEXP ) || !victim.IsNPC() ) GroupExperienceGain( ch, victim ); if( ch.IsNPC() ) { if( ch.Hunting ) { if( ch.Hunting.Who == victim ) StopHunting( ch ); } if( ch.IsHating(victim) ) { ch.StopHating( victim ); } } if( !victim.IsNPC() ) { if( ch.IsNPC() ) { ( (PC)victim ).MobDeaths++; if( victim.IsGuild() ) { ( (PC)victim ).GuildMembership.MonsterDeaths++; ( (PC)victim ).GuildMembership.Score += CalculateDeathScore( ch, victim ); } ( (PC)victim ).Score += CalculateDeathScore( ch, victim ); } else { ( (PC)ch ).PlayerKills++; ( (PC)victim ).PlayerDeaths++; ( (PC)victim ).Score += CalculateDeathScore( ch, victim ); ( (PC)ch ).Score += CalculateKillScore( ch, victim ); if( ch.IsGuild() && victim.IsGuild() && ( (PC)ch ).GuildMembership != ( (PC)victim ).GuildMembership ) { ( (PC)ch ).GuildMembership.PlayerKills++; ( (PC)victim ).GuildMembership.PlayerDeaths++; ( (PC)ch ).GuildMembership.Score += CalculateKillScore( ch, victim ); ( (PC)victim ).GuildMembership.Score += CalculateDeathScore( ch, victim ); } } string logBuf = String.Format( "{0}&n killed by {1}&n at {2}", victim.Name, ( ch.IsNPC() ? ch.ShortDescription : ch.Name ), victim.InRoom.IndexNumber ); Log.Trace( logBuf ); ImmortalChat.SendImmortalChat( ch, ImmortalChat.IMMTALK_DEATHS, Limits.LEVEL_AVATAR, logBuf ); /* * Dying penalty: * * At level 1 you lose 12.5% of a level. * At level 50 you lose 25% of a level. */ // Made it so people level 5 and under lose no exp from death. if( ch.Level > 5 ) victim.GainExperience( ( 0 - ( ( ( 50 + victim.Level ) * ExperienceTable.Table[ victim.Level ].LevelExperience ) / 400 ) ) ); if( victim.Level < 2 && victim.ExperiencePoints < 1 ) victim.ExperiencePoints = 1; } else { if( !ch.IsNPC() ) { ( (PC)ch ).MobKills++; if( ch.IsGuild() ) { ( (PC)ch ).GuildMembership.MonsterKills++; ( (PC)ch ).GuildMembership.Score += CalculateKillScore( ch, victim ); } ( (PC)ch ).Score += CalculateKillScore( ch, victim ); } } KillingBlow( ch, victim ); return true; } if( victim == ch ) { return false; } /* * Wimp out? */ if( victim.IsNPC() && dam > 0 ) { if( ( victim.HasActionBit(MobTemplate.ACT_WIMPY ) && MUDMath.NumberBits( 1 ) == 0 && victim.Hitpoints < victim.GetMaxHit() / 5 ) || (victim.IsAffected( Affect.AFFECT_CHARM) && victim.Master && victim.Master.InRoom != victim.InRoom ) ) { StartFearing( victim, ch ); StopHunting( victim ); CommandType.Interpret(victim, "flee"); } } if( !victim.IsNPC() && victim.Hitpoints > 0 && victim.Hitpoints <= victim.Wimpy ) { CommandType.Interpret(victim, "flee"); } return false; }
/// <summary> /// Checks whether two characters are in the same guild. /// </summary> /// <param name="ch"></param> /// <returns></returns> public bool IsSameGuild( CharData ch ) { if (IsGuild() && ch.IsGuild()) { return ((PC)this).GuildMembership == ((PC)ch).GuildMembership; } return false; }
public static void Fine(CharData ch, string[] str) { if( ch == null ) return; string arg = String.Empty; int amount; int count; if (arg.Length == 0) { ch.SendText("Fine whom?\r\n"); return; } if (!ch.IsGuild() || ((PC)ch).GuildRank < Guild.Rank.deputy) { ch.SendText("You don't have the power to do this.\r\n"); return; } Guild guild = ((PC)ch).GuildMembership; Int32.TryParse(str[0], out amount); if (amount <= 0) { ch.SendText("Fine them how much?\r\n"); return; } if (!MUDString.StringsNotEqual(arg, "all")) { for (count = 0; count < Limits.MAX_GUILD_MEMBERS; ++count) { if (guild.Members[count].Filled == true && guild.Members[count].Rank < ((PC)ch).GuildRank) { guild.Members[count].Fine += amount; } } } else { bool found = false; for (count = 0; count < Limits.MAX_GUILD_MEMBERS; ++count) { if (MUDString.StringsNotEqual(guild.Members[count].Name, arg)) continue; if (guild.Members[count].Filled == true && guild.Members[count].Rank < ((PC)ch).GuildRank) { guild.Members[count].Fine += amount; found = true; } } if (!found) { ch.SendText("You were not able to fine them.\r\n"); return; } } ch.SendText("Done.\r\n"); guild.Save(); return; }
/// <summary> /// Terminate your guild membership. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Leave(CharData ch, string[] str) { if( ch == null ) return; if (!ch.IsGuild()) { ch.SendText("You aren't a guildmember.\r\n"); return; } Guild guild = ((PC)ch).GuildMembership; if (((PC)ch).GuildRank == Guild.Rank.leader) { ch.SendText("Huh? An Overlord shouldn't leave his guild! Get demoted first!\r\n"); return; } ch.RemoveFromGuild(); ((PC)ch).GuildRank = Guild.Rank.normal; SocketConnection.Act("You have left guild $t.", ch, guild.WhoName, ch, SocketConnection.MessageTarget.character); CharData.SavePlayer(ch); guild.Save(); return; }
/// <summary> /// Shows details about a guild. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void GuildInfo(CharData ch, string[] str) { if( ch == null ) return; int count; int members = 0; if (!ch.IsGuild()) { ch.SendText("You aren't a guildmember.\r\n"); return; } Guild guild = ((PC)ch).GuildMembership; string buf1 = String.Empty; string text = String.Format("{0}\r\n", guild.Name); buf1 += text; text = String.Format("Motto: \"{0}\"\r\n", guild.Motto); buf1 += text; buf1 += "-----------------------------------------------------------------------------\r\n"; text = String.Format("{0}\r\n", guild.Description); buf1 += text; text = String.Format("Leader: {0}\r\n", guild.Overlord); buf1 += text; text = String.Format("Members: {0}\r\nFrags: &+W{1}&n\r\n", guild.NumMembers, guild.Frags); buf1 += text; text = String.Format("Vault: {0} &+Wplatinum&n, {1} &+Ygold&n, {2} silver, {3} &+ycopper&n\r\n", guild.GuildBankAccount.Platinum, guild.GuildBankAccount.Gold, guild.GuildBankAccount.Silver, guild.GuildBankAccount.Copper); buf1 += text; text = String.Format("Current Applicant: {0}\r\n", guild.Applicant ? guild.Applicant.Name : "(none)"); buf1 += text; if (((PC)ch).GuildRank == Guild.Rank.leader) { text = String.Format("\r\n&+cRank Titles:&n\r\n Exile: {0}\r\n Parole: {1}\r\n Normal: {2}\r\n Senior: {3}\r\n" + " Officer: {4}\r\n Deputy: {5}\r\n Leader: {6}\r\n", guild.RankNames[(int)Guild.Rank.exiled], guild.RankNames[(int)Guild.Rank.parole], guild.RankNames[(int)Guild.Rank.normal], guild.RankNames[(int)Guild.Rank.senior], guild.RankNames[(int)Guild.Rank.officer], guild.RankNames[(int)Guild.Rank.deputy], guild.RankNames[(int)Guild.Rank.leader]); buf1 += text; } text = String.Format("\r\nMember Rank Fine:\r\n"); buf1 += text; for (count = 0; count < Limits.MAX_GUILD_MEMBERS; ++count) { if (guild.Members[count].Filled) { members++; text = String.Format("{0}) &+r{1}&n{2} {3} {4}&+yc&n\r\n", members, (ch.GetCharWorld(guild.Members[count].Name) ? 'o' : ' '), MUDString.PadStr(guild.Members[count].Name, 15), guild.RankNames[(int)guild.Members[count].Rank], MUDString.PadInt(guild.Members[count].Fine, 8)); buf1 += text; } } if (guild.Ostracized.Length > 0) { text = String.Format("Ostracized: {0}\r\n", guild.Ostracized); buf1 += text; } ch.SendText(buf1); return; }
/// <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; }