/// <summary> /// Capture command - restrain another character. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Capture(CharData ch, string[] str) { if( ch == null ) return; CharData victim; Affect af = new Affect(); /* Check player's level and class, allow mobs to do this too */ if ((!ch.HasSkill("capture"))) { ch.SendText("You couldn't capture a dead rat.\r\n"); return; } if (str.Length == 0) { victim = ch.Fighting; if (!victim) { ch.SendText("Capture whom?\r\n"); return; } } else /* argument supplied */ { victim = ch.GetCharRoom(str[0]); if (!victim) { ch.SendText("They aren't here.\r\n"); return; } } if (ch.Fighting && ch.Fighting != victim) { ch.SendText("Take care of the person you are fighting first!\r\n"); return; } if (!ch.IsImmortal()) { ch.WaitState(Skill.SkillList["capture"].Delay); } Object rope = Object.GetEquipmentOnCharacter(ch, ObjTemplate.WearLocation.hand_one); if (!rope || rope.ItemType != ObjTemplate.ObjectType.rope) { rope = Object.GetEquipmentOnCharacter(ch, ObjTemplate.WearLocation.hand_two); if (!rope || rope.ItemType != ObjTemplate.ObjectType.rope) { rope = Object.GetEquipmentOnCharacter(ch, ObjTemplate.WearLocation.hand_three); if (!rope || rope.ItemType != ObjTemplate.ObjectType.rope) { rope = Object.GetEquipmentOnCharacter(ch, ObjTemplate.WearLocation.hand_four); if (!rope || rope.ItemType != ObjTemplate.ObjectType.rope) rope = null; } } } if (!rope) { ch.SendText("You must have some rope to tie someone up!\r\n"); return; } rope.RemoveFromWorld(); /* only appropriately skilled PCs and uncharmed mobs */ if ((ch.IsNPC() && !ch.IsAffected( Affect.AFFECT_CHARM)) || (!ch.IsNPC() && MUDMath.NumberPercent() < ((PC)ch).SkillAptitude["capture"] / 4)) { victim.AffectStrip( Affect.AffectType.skill, "capture"); af.Value = "capture"; af.Type = Affect.AffectType.skill; af.Duration = 3 + ((ch.Level) / 8); af.SetBitvector(Affect.AFFECT_BOUND); victim.AddAffect(af); SocketConnection.Act("You have captured $M!", ch, null, victim, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n has captured you!", ch, null, victim, SocketConnection.MessageTarget.victim); SocketConnection.Act("$n&n has captured $N&n.", ch, null, victim, SocketConnection.MessageTarget.everyone_but_victim); } else { SocketConnection.Act("You failed to capture $M. Uh oh!", ch, null, victim, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n tried to capture you! Get $m!", ch, null, victim, SocketConnection.MessageTarget.victim); SocketConnection.Act("$n&n attempted to capture $N&n, but failed!", ch, null, victim, SocketConnection.MessageTarget.everyone_but_victim); } /* go for the one who wanted to fight :) */ if (ch.IsNPC() && ch.IsAffected( Affect.AFFECT_CHARM) && !victim.Fighting) { victim.AttackCharacter(ch.Master); } else if (!victim.Fighting) { victim.AttackCharacter(ch); } return; }
/// <summary> /// Tracking mob has found the person its after. Attack or react accordingly. /// </summary> /// <param name="ch"></param> /// <param name="victim"></param> public static void FoundPrey( CharData ch, CharData victim ) { string victname = String.Empty; string text = String.Empty; string lbuf = String.Empty; if (!victim) { Log.Error("FoundPrey: null victim", 0); return; } if (!victim.InRoom) { Log.Error("FoundPrey: null victim._inRoom", 0); return; } ImmortalChat.SendImmortalChat(null, ImmortalChat.IMMTALK_HUNTING, 0, string.Format("{0}&n has found {1}.", ch.ShortDescription, victim.Name)); if (ch.IsAffected(Affect.AFFECT_TRACK)) { ch.RemoveAffect(Affect.AFFECT_TRACK); Combat.StopHunting(ch); return; } if (ch.IsAffected(Affect.AFFECT_JUSTICE_TRACKER)) { /* Give Justice the ability to ground flying culprits */ if (victim.FlightLevel != 0) { SocketConnection.Act("$n&n forces you to land!", ch, null, victim, SocketConnection.MessageTarget.victim); SocketConnection.Act("$n&n forces $N&n to land!", ch, null, victim, SocketConnection.MessageTarget.room_vict); victim.FlightLevel = 0; } SocketConnection.Act("$n&n says, 'Stop, $N&n, you're under ARREST!'", ch, null, victim, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n says, 'Stop, $N&n, you're under ARREST!'", ch, null, victim, SocketConnection.MessageTarget.room); SocketConnection.Act("$n&n chains you up.", ch, null, victim, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n binds $N&n so $E can't move.", ch, null, victim, SocketConnection.MessageTarget.room); victim.SetAffectBit(Affect.AFFECT_BOUND); victim.RemoveFromRoom(); if (ch.InRoom.Area.JailRoom != 0) { victim.AddToRoom(Room.GetRoom(victim.InRoom.Area.JailRoom)); } else { victim.SendText("Justice is broken in this town - there is no jail and you're screwed.\r\n"); } Combat.StopHunting(ch); return; } victname = victim.IsNPC() ? victim.ShortDescription : victim.Name; if (ch.FlightLevel != victim.FlightLevel) { if (ch.CanFly()) { if (ch.FlightLevel < victim.FlightLevel && ch.FlightLevel < CharData.FlyLevel.high) { Command.Fly(ch, new string[] { "up" }); } else { Command.Fly(ch, new string[] { "down" }); } } else { SocketConnection.Act("$n peers around looking for something.", ch, null, null, SocketConnection.MessageTarget.room); } return; } if (!CharData.CanSee(ch, victim)) { if (MUDMath.NumberPercent() < 90) return; switch (MUDMath.NumberBits(5)) { case 0: text = String.Format("You can't hide forever, {0}!", victname); Command.Say(ch, new string[]{text}); break; case 1: SocketConnection.Act("$n&n sniffs around the room.", ch, null, victim, SocketConnection.MessageTarget.room); text = "I can smell your blood!"; Command.Say(ch, new string[]{text}); break; case 2: text = String.Format("I'm going to tear {0} apart!", victname); Command.Yell(ch, new string[]{text}); break; case 3: Command.Say(ch, new string[]{"Just wait until I find you..."}); break; default: SocketConnection.Act("$p peers about looking for something.", ch, null, null, SocketConnection.MessageTarget.room); break; } return; } if (ch.InRoom.HasFlag(RoomTemplate.ROOM_SAFE) && ch.IsNPC()) { text = String.Format("Hunting mob {0} found a safe room {1}.", ch.MobileTemplate.IndexNumber, ch.InRoom.IndexNumber); Log.Trace(text); return; } if (ch.CurrentPosition > Position.kneeling) { switch (MUDMath.NumberBits(5)) { case 0: text = String.Format("I will eat your heart, {0}!", victname); Command.Say(ch, new string[]{text}); break; case 1: text = String.Format("You want a piece of me, {0}?", victname); Command.Say(ch, new string[]{text}); break; case 2: text = String.Format("How does your flesh taste {0}, like chicken?", victname); Command.Say(ch, new string[]{text}); break; case 3: SocketConnection.Act("$n&n howls gleefully and lunges at $N&n!", ch, null, victim, SocketConnection.MessageTarget.everyone_but_victim); SocketConnection.Act("$n&n howls gleefully and lunges at you!", ch, null, victim, SocketConnection.MessageTarget.victim); break; case 4: SocketConnection.Act("$n&n charges headlong into $N&n!", ch, null, victim, SocketConnection.MessageTarget.everyone_but_victim); SocketConnection.Act("$n&n charges headlong into you!", ch, null, victim, SocketConnection.MessageTarget.victim); break; default: break; } Combat.StopHunting(ch); Combat.CheckAggressive(victim, ch); if (ch.Fighting) return; // Backstab if able, otherwise just kill them. // Kill if they don't have the skill or if they don't have a stabber. if (!ch.HasSkill("backstab")) { Combat.CombatRound(ch, victim, String.Empty); } else if (!Combat.Backstab(ch, victim)) { Combat.CombatRound(ch, victim, String.Empty); } } return; }
public static void ReturnToLoad( CharData ch ) { if( !ch || !ch.InRoom ) return; if( ch.InRoom.Area != Room.GetRoom( ch.LoadRoomIndexNumber ).Area ) return; Exit.Direction dir = FindPath( ch.InRoom.IndexNumber, ch.LoadRoomIndexNumber, ch, -40000, true ); if( dir == Exit.Direction.invalid ) { return; } if( ch.InRoom.ExitData[ (int)dir ].HasFlag( Exit.ExitFlag.closed ) && !ch.IsAffected( Affect.AFFECT_PASS_DOOR ) && !ch.HasInnate( Race.RACE_PASSDOOR ) ) { CommandType.Interpret(ch, "unlock " + dir.ToString()); CommandType.Interpret(ch, "open " + dir.ToString()); return; } ch.Move( dir ); if( !ch.InRoom ) { string text = "Return_to_load: no ch._inRoom! Mob #" + ch.MobileTemplate.IndexNumber + ", _name: " + ch.Name + ". Placing mob in limbo (mob.AddToRoom())."; Log.Error( text, 0 ); ch.AddToRoom( Room.GetRoom( StaticRooms.GetRoomNumber("ROOM_NUMBER_LIMBO") ) ); ImmortalChat.SendImmortalChat(ch, ImmortalChat.IMMTALK_SPAM, 0, text); return; } return; }
/// <summary> /// Pick up an item. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Get(CharData ch, string[] str) { if( ch == null ) return; Object container; bool found; Object obj; if (ch.IsAffected(Affect.AFFECT_HOLD) || ch.IsAffected(Affect.AFFECT_MINOR_PARA)) { ch.SendText("Try as you might, your body refuses to move!\r\n"); return; } /* Get type. */ if (str.Length == 0 || String.IsNullOrEmpty(str[0])) { ch.SendText("Get what?\r\n"); return; } if (str.Length < 2) { if (str[0] != "all" && MUDString.IsPrefixOf("all.", str[0])) { /* 'get obj' */ obj = Object.GetObjFromList(ch.InRoom.Contents, ch, str[0]); if (obj == null) { SocketConnection.Act("I see no $T&n here.", ch, null, str[0], SocketConnection.MessageTarget.character); return; } if (ch.CarryNumber + 1 > Limits.MAX_CARRY) { ch.SendText("You have your hands full.\r\n"); return; } Object.GetObject(ch, obj, null); } else { /* 'get all' or 'get all.obj' */ found = false; for(int i = (ch.InRoom.Contents.Count - 1); i >= 0; i--) { Object iobj = ch.InRoom.Contents[i]; if (iobj.FlyLevel != ch.FlightLevel) { continue; } if ((str[0].Equals("all", StringComparison.CurrentCultureIgnoreCase) || MUDString.NameContainedIn(str[0].Substring(4), iobj.Name)) && CharData.CanSeeObj(ch, iobj)) { found = true; if (ch.CarryNumber + 1 > Limits.MAX_CARRY) { ch.SendText("You have your hands full.\r\n"); return; } Object.GetObject(ch, iobj, null); } } if (!found) { if (str[0].Equals("all", StringComparison.CurrentCultureIgnoreCase)) { ch.SendText("You see nothing here.\r\n"); } else { SocketConnection.Act("You see no $T&n here.", ch, null, str[0].Substring(4), SocketConnection.MessageTarget.character); } } } } else { /* 'get ... container' */ if (!MUDString.StringsNotEqual(str[1], "all") || !MUDString.IsPrefixOf("all.", str[1])) { ch.SendText("That doesn't seem possible.\r\n"); return; } container = ch.GetObjHere(str[1]); if (!container) { SocketConnection.Act("You don't see any $T&n here.", ch, null, str[1], SocketConnection.MessageTarget.character); return; } switch (container.ItemType) { default: ch.SendText("Unfortunately, that's not a container.\r\n"); return; case ObjTemplate.ObjectType.quiver: case ObjTemplate.ObjectType.container: case ObjTemplate.ObjectType.npc_corpse: break; case ObjTemplate.ObjectType.pc_corpse: { string descr = container.ShortDescription; string name = String.Empty; } break; } if (ch.CurrentPosition == Position.fighting || ch.Fighting) { ch.SendText("You're too busy to be doing that!\r\n"); return; } if (Macros.IsSet(container.Values[1], ObjTemplate.CONTAINER_CLOSED.Vector)) { SocketConnection.Act("The $d&n is fastened shut.", ch, null, container.Name, SocketConnection.MessageTarget.character); return; } if (str[0] != "all" && MUDString.IsPrefixOf("all.", str[0])) { /* 'get obj container' */ obj = Object.GetObjFromList(container.Contains, ch, str[0]); if (!obj) { SocketConnection.Act("You search the $T&n with little success.", ch, null, str[1], SocketConnection.MessageTarget.character); return; } if (ch.CarryNumber + 1 > Limits.MAX_CARRY) { ch.SendText("You have your hands full.\r\n"); return; } Object.GetObject(ch, obj, container); } else { /* 'get all container' or 'get all.obj container' */ found = false; for( int i = (container.Contains.Count - 1); i >= 0; i--) { if ((str[0].Equals("all", StringComparison.CurrentCultureIgnoreCase) || MUDString.NameContainedIn(str[0].Substring(4), container.Contains[i].Name)) && CharData.CanSeeObj(ch, container.Contains[i])) { found = true; if (ch.CarryNumber + 1 > Limits.MAX_CARRY) { ch.SendText("You have your hands full.\r\n"); return; } Object.GetObject(ch, container.Contains[i], container); if (container.ItemType == ObjTemplate.ObjectType.pc_corpse) { CharData.SavePlayer(ch); Database.CorpseList.Save(); } } } if (!found) { if (str[0].Equals("all", StringComparison.CurrentCultureIgnoreCase)) { SocketConnection.Act("You see nothing in the $T&n.", ch, null, str[1], SocketConnection.MessageTarget.character); } else { SocketConnection.Act("You see nothing like that in the $T&n.", ch, null, str[1], SocketConnection.MessageTarget.character); } } } } return; }
/// <summary> /// Hide yourself or an object. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Hide(CharData ch, string[] str) { if( ch == null ) return; /* Check player's skill */ if (!ch.HasSkill("hide")) { if(str.Length != 0) { HideItem(ch, new[] { str[0] }); return; } ch.SendText("You're far too obvious to hide anywhere.\r\n"); return; } if (ch.Riding) { ch.SendText("You can't do that while mounted.\r\n"); return; } if (ch.CurrentPosition <= Position.sleeping) { return; } ch.SendText("You attempt to hide.\r\n"); if (ch.IsAffected(Affect.AFFECT_HIDE)) { ch.RemoveAffect(Affect.AFFECT_HIDE); } if (ch.CheckSkill("hide")) { ch.SetAffectBit(Affect.AFFECT_HIDE); } ch.WaitState(12); return; }
/// <summary> /// Enter a portal. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Enter(CharData ch, string[] str) { if( ch == null ) return; Room location; bool ship = false; if (str.Length == 0) { ch.SendText("Enter what?\r\n"); return; } if (ch.Fighting) { ch.SendText("Not while you're fighting!\r\n"); return; } Room original = ch.InRoom; Object portal = Object.GetObjFromList(ch.InRoom.Contents, ch, str[0]); if (!portal) { SocketConnection.Act("There is no $t in here.", ch, str[0], null, SocketConnection.MessageTarget.character); return; } if (portal.ItemType != ObjTemplate.ObjectType.portal) { if (portal.ItemType != ObjTemplate.ObjectType.ship && portal.ItemType != ObjTemplate.ObjectType.vehicle) { ch.SendText("That's not a portal.\r\n"); return; } ship = true; } if (!ship) { if (Macros.IsSet(portal.Values[3], ObjTemplate.PORTAL_CLOSED)) { ch.SendText("That portal is closed.\r\n"); return; } if (portal.Values[2] == 0) { SocketConnection.Act("$p&n has no power left.", ch, portal, null, SocketConnection.MessageTarget.character); return; } if (!Macros.IsSet(portal.Values[3], ObjTemplate.PORTAL_NO_CURSED) && (ch.IsAffected( Affect.AFFECT_CURSE) )) { ch.SendText("Your deity has forsaken you.\r\n"); return; } location = Room.GetRoom(portal.Values[0]); if (Macros.IsSet(portal.Values[3], ObjTemplate.PORTAL_BUGGY) && MUDMath.NumberPercent() < 5) { location = Movement.GetRandomRoom(); } if (Macros.IsSet(portal.Values[3], ObjTemplate.PORTAL_RANDOM)) { location = Movement.GetRandomRoom(); portal.Values[0] = location.IndexNumber; } if (!location) { ch.SendText("The target room for this portal does not exist.\r\n"); return; } if (location == original) { SocketConnection.Act("$p&n doesn't seem to go anywhere.", ch, portal, null, SocketConnection.MessageTarget.character); return; } } else { location = Room.GetRoom(portal.Values[1]); if (!location) { ch.SendText("That boat is broken. You may not board it.\r\n"); return; } } if (location.IsPrivate()) { ch.SendText("There is no room for you on the other side.\r\n"); return; } if (!ship) { SocketConnection.Act("$n&n steps into $p&n.", ch, portal, null, SocketConnection.MessageTarget.room); if (Macros.IsSet(portal.Values[3], ObjTemplate.PORTAL_RANDOM) || Macros.IsSet(portal.Values[3], ObjTemplate.PORTAL_BUGGY)) { SocketConnection.Act("You walk through $p&n and find yourself somewhere else...", ch, portal, null, SocketConnection.MessageTarget.character); } else { SocketConnection.Act("You enter $p&n.", ch, portal, null, SocketConnection.MessageTarget.character); } } else { SocketConnection.Act("$n&n boards $p&n.", ch, portal, null, SocketConnection.MessageTarget.room); SocketConnection.Act("You board $p&n.", ch, portal, null, SocketConnection.MessageTarget.character); } ch.RemoveFromRoom(); ch.AddToRoom(location); if (!ship) { if (Macros.IsSet(portal.Values[3], ObjTemplate.PORTAL_RANDOM) || Macros.IsSet(portal.Values[3], ObjTemplate.PORTAL_BUGGY)) { SocketConnection.Act("$n&n has arrived from elsewhere.", ch, portal, null, SocketConnection.MessageTarget.room); } else { SocketConnection.Act("$n&n steps out of $p&n.", ch, portal, null, SocketConnection.MessageTarget.room); } } else { SocketConnection.Act("$n&n has boarded.", ch, portal, null, SocketConnection.MessageTarget.room); } CommandType.Interpret(ch, "look auto"); if (!ship) { if (portal.Values[2] > 0) /* * This way i prevent an underflow */ portal.Values[2]--; if (portal.Values[2] == 0)/* * If there are no more charges; remove */ { SocketConnection.Act("$p&n fades out of existence.", ch, portal, null, SocketConnection.MessageTarget.character); SocketConnection.Act("$p&n fades out of existence.", ch, portal, null, SocketConnection.MessageTarget.room); portal.RemoveFromWorld(); return; } if (Macros.IsSet(portal.Values[3], ObjTemplate.PORTAL_GO_WITH)) { portal.RemoveFromRoom(); portal.AddToRoom(location); } } foreach (CharData follower in original.People) { if (!follower.IsAffected(Affect.AFFECT_CHARM) || follower.Master != ch) { continue; } if (follower.CurrentPosition < Position.standing) { CommandType.Interpret(ch, "stand"); } if (follower.CurrentPosition == Position.standing && follower.Wait == 0) { SocketConnection.Act("You follow $N&n.", follower, null, ch, SocketConnection.MessageTarget.character); Enter(follower, str); } } return; }
public static void Aware(CharData ch, string[] str) { if( ch == null ) return; Affect af = new Affect(); if (ch.IsNPC()) return; if (!ch.HasSkill("awareness")) { ch.SendText("Your general obliviousness prevents your use of this skill.\r\n"); return; } if (ch.IsAffected(Affect.AFFECT_SKL_AWARE)) { ch.SendText("You are already about as tense as you can get.\r\n"); return; } ch.SendText("You try to become more aware of your surroundings.\r\n"); ch.PracticeSkill("awareness"); af.Value = "awareness"; af.Type = Affect.AffectType.skill; af.Duration = (ch.Level / 3) + 3; af.SetBitvector(Affect.AFFECT_SKL_AWARE); ch.AddAffect(af); return; }
/// <summary> /// Shows the world map. Can be called from the look command or called directly. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Worldmap(CharData ch, string[] str) { int x; Room room; if (ch.InRoom == null) { return; } if (!ch.InRoom.Area.HasFlag(Area.AREA_WORLDMAP)) { return; } // TODO: Use Map.GetUnderdarkVisibilityModifier(racewarside) and Map.GetDaytimeVisibilityModifier(racewarside) int visibility = 5 + (int)ch.FlightLevel; // Godmode will make you see farther on the map. if (!ch.IsNPC() && ch.HasActionBit(PC.PLAYER_GODMODE)) { visibility += 5; } int indexNumber = ch.InRoom.IndexNumber; int startIndexNumber = ch.InRoom.Area.LowRoomIndexNumber; int column = (indexNumber - startIndexNumber) % ch.InRoom.Area.Width; int row = (indexNumber - startIndexNumber) / ch.InRoom.Area.Width; if (visibility <= 0 && !ch.IsAffected(Affect.AFFECT_BLIND)) { visibility = 1; } if (visibility > Limits.MAX_MAP_VISIBILITY) { visibility = Limits.MAX_MAP_VISIBILITY; } string mapSpaces = String.Empty; string lineEnding = ":"; string mapClose = "</map>"; string text = "<map>"; string boundchar = " "; bool graphicalClient = !ch.IsNPC() && ch.Socket.Terminal == SocketConnection.TerminalType.TERMINAL_ENHANCED; if (!graphicalClient) { boundchar = "&-L &n"; mapSpaces = " "; lineEnding = "\r\n"; mapClose = "\r\n"; text = "\r\n"; } for (x = (0 - Limits.MAX_MAP_VISIBILITY); x <= Limits.MAX_MAP_VISIBILITY; x++) { if (graphicalClient) { text += (x + Limits.MAX_MAP_VISIBILITY).ToString() + "|"; } else if (x < (0 - visibility) || x > (visibility)) { continue; } text += mapSpaces; int y; for (y = (0 - Limits.MAX_MAP_VISIBILITY); y <= Limits.MAX_MAP_VISIBILITY; y++) { if(x < (0 - visibility) || x > (visibility)) { if (graphicalClient) { text += boundchar; } else { continue; } } bool hasM = false; bool hasP = false; room = Room.GetRoom((indexNumber + ((x * ch.InRoom.Area.Width) + y))); if (room && room.People.Count > 0) { foreach (CharData roomChar in room.People) { if ((roomChar.FlightLevel == ch.FlightLevel || ch.FlightLevel == roomChar.FlightLevel + 1) && CharData.CanSee(ch, roomChar)) { if (roomChar.IsNPC()) { if (roomChar.FlightLevel == ch.FlightLevel) { hasM = true; } else { hasM = false; } } else { if (roomChar.FlightLevel == ch.FlightLevel) { hasP = true; } else { hasP = false; } } } } } if (x == 0 && y == 0) { if (graphicalClient) { String chars = Map.GetMapCharacters(room, graphicalClient); // Pick a diff character based on player's size. text += chars[0]; int offset = 64; if (ch.CurrentSize >= Race.Size.large && ch.CurrentSize <= Race.Size.gargantuan) { text += (char)(24 + offset); // Large humanoid } else if( ch.CurrentSize <= Race.Size.small && ch.CurrentSize >= Race.Size.tiny ) { text += (char)(28 + offset); // Small humanoid } else { text += (char)(26 + offset); // Medium humanoid } } else { text += "&+W@&n"; } } else if ((column + y) < 0 || (column + y) >= ch.InRoom.Area.Width || (row + x) < 0 || (row + x) >= ch.InRoom.Area.Height) { text += boundchar; } else if (!(room = Room.GetRoom((indexNumber + ((x * ch.InRoom.Area.Width) + y))))) { if (graphicalClient) { text += boundchar; } else { text += "&+L-&n"; } } else if (hasM) { if (graphicalClient) { text += "*"; } else { text += Color.MOD_BLINK + "&+BM&n" + Color.MOD_CLEAR; } } else if (hasP) { if (graphicalClient) { text += "!"; } else { text += Color.MOD_BLINK + "&+WP&n" + Color.MOD_CLEAR; } } else { text += Map.GetMapCharacters(room, graphicalClient); } } text += lineEnding; /* Added these two lines to make it smaller string size in send_to_chr, * so that the pager isnt needed when large maps fill the screen */ ch.SendText(text); text = String.Empty; } text += mapClose; ch.SendText(text); return; }
/// <summary> /// Command to cast a spell. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Cast(CharData ch, string[] str) { if( ch == null ) return; if ((ch.IsClass(CharClass.Names.psionicist) || ch.IsClass(CharClass.Names.enslaver)) && !ch.IsImmortal()) { ch.SendText("Psionicists use the WILL command to invoke their powers.\r\n"); return; } if (ch.IsClass(CharClass.Names.bard) && !ch.IsImmortal()) { ch.SendText("Bards use the SING or PLAY commands to invoke their powers.\r\n"); return; } if (ch.Riding && ch.InRoom == ch.Riding.InRoom) { ch.SendText("You cannot cast while mounted!\r\n"); return; } if (ch.IsAffected( Affect.AFFECT_MINOR_PARA) || ch.IsAffected( Affect.AFFECT_HOLD)) { ch.SendText("You can't cast when you're paralyzed!\r\n"); return; } if (str.Length == 0) { ch.SendText("Cast what spell where?\r\n"); return; } Magic.Cast(ch, String.Join(" ", str)); }
/// <summary> /// Put on a piece of equipment. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Wear(CharData ch, string[] str) { if( ch == null ) return; Object obj; if (ch.IsAffected(Affect.AFFECT_HOLD) || ch.IsAffected(Affect.AFFECT_MINOR_PARA)) { ch.SendText("Your body refuses the call to movement.\r\n"); return; } if (!ch.IsNPC() && ch.IsAffected( Affect.AFFECT_WRAITHFORM)) { ch.SendText("You try, but your &n&+wghoul&n form resists your attempts.\r\n"); return; } if (ch.Fighting || ch.CurrentPosition == Position.fighting) { ch.SendText("You can't wear stuff while you're fighting!\r\n"); return; } if (str.Length == 0) { ch.SendText("Wear, wield, or hold what?\r\n"); return; } if (str[0] == "all") { foreach (Object iobj in ch.Carrying) { if (iobj.WearLocation != ObjTemplate.WearLocation.none || !CharData.CanSeeObj(ch, iobj)) { continue; } if (iobj.HasWearFlag(ObjTemplate.WEARABLE_WIELD) && !ch.HasInnate(Race.RACE_WEAPON_WIELD)) { continue; } Object.WearObject(ch, iobj, false); if (iobj.Trap != null && iobj.Trap.CheckTrigger( Trap.TriggerType.wear)) { ch.SetOffTrap(iobj); if (ch.CurrentPosition == Position.dead) { return; } } } return; } if (!(obj = ch.GetObjCarrying(str[0]))) { ch.SendText("You do not have that item.\r\n"); return; } if (obj.HasWearFlag(ObjTemplate.WEARABLE_WIELD) && !ch.HasInnate(Race.RACE_WEAPON_WIELD)) { ch.SendText("You are not able to wield a weapon.\r\n"); return; } Object.WearObject(ch, obj, true); if (obj.Trap != null && obj.Trap.CheckTrigger( Trap.TriggerType.wear)) { ch.SetOffTrap(obj); if (ch.CurrentPosition == Position.dead) { return; } } return; }
/// <summary> /// Equip a weapon. Now calls equip_hand to resolve the actual equipping /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Wield(CharData ch, string[] str) { if( ch == null ) return; Object obj; if (ch.IsAffected(Affect.AFFECT_HOLD) || ch.IsAffected( Affect.AFFECT_MINOR_PARA)) { ch.SendText("Your body refuses the call to movement.\r\n"); return; } if (!ch.IsNPC() && ch.IsAffected( Affect.AFFECT_WRAITHFORM)) { ch.SendText("You try, but your &n&+wghoul&n form resists your attempts.\r\n"); return; } if (str.Length == 0) { ch.SendText("Wield what?\r\n"); return; } if (!(obj = ch.GetObjCarrying(str[0]))) { ch.SendText("You do not have that item.\r\n"); return; } if (!obj.HasWearFlag(ObjTemplate.WEARABLE_WIELD)) { if (obj.ItemType == ObjTemplate.ObjectType.weapon) { ch.SendText("That object is not usable as a weapon.\r\n"); return; } if (obj.ItemType == ObjTemplate.ObjectType.ranged_weapon && !obj.HasWearFlag(ObjTemplate.WEARABLE_HOLD)) { ch.SendText("That object is not usable as a missile weapon.\r\n"); return; } if (obj.ItemType == ObjTemplate.ObjectType.ranged_weapon) { // Ranged weapons flagged wither wield or hold are fine to use -- Xangis } else { ch.SendText("That object is not a weapon.\r\n"); return; } } if (!ch.HasInnate(Race.RACE_WEAPON_WIELD)) { ch.SendText("You are not able to wield a weapon.\r\n"); return; } if (!obj.IsWearableBy(ch)) return; Object.EquipInHand(ch, obj, Object.EQUIP_WIELD); return; }
/// <summary> /// Lets a player go visible if they want to. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Visible(CharData ch, string[] str) { if( ch == null ) return; if (!ch.IsAffected(Affect.AFFECT_INVISIBLE) && !ch.IsAffected(Affect.AFFECT_MINOR_INVIS) && !ch.IsAffected(Affect.AFFECT_DUERGAR_HIDE)) { ch.SendText("You already stick out like a &+Rsore thumb&n.\r\n" ); return; } ch.RemoveAffect(Affect.AFFECT_INVISIBLE); ch.RemoveAffect(Affect.AFFECT_MINOR_INVIS); ch.RemoveAffect(Affect.AFFECT_DUERGAR_HIDE); ch.SendText("You make yourself visible.\r\n"); SocketConnection.Act("$n&n slowly fades into existence.\r\n", ch, null, null, SocketConnection.MessageTarget.room ); return; }
/// <summary> /// Try to free someone who has been bound. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Untangle(CharData ch, string[] str) { if( ch == null ) return; CharData victim; if (!ch.IsNPC() && !ch.HasSkill("untangle")) { ch.SendText("You aren't nimble enough.\r\n"); return; } if (str.Length == 0) { victim = ch; } else { victim = ch.GetCharRoom(str[0]); if (victim == null) { ch.SendText("They aren't here.\r\n"); return; } } if (!victim.HasAffect( Affect.AffectType.skill, "capture")) { ch.SendText("There's nothing to untangle.\r\n"); return; } if ((ch.IsNPC() && !ch.IsAffected( Affect.AFFECT_CHARM)) || (!ch.IsNPC() && MUDMath.NumberPercent() < ((PC)ch).SkillAptitude["untangle"])) { victim.AffectStrip( Affect.AffectType.skill, "capture"); if (victim != ch) { SocketConnection.Act("You untangle $N&n.", ch, null, victim, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n untangles you.", ch, null, victim, SocketConnection.MessageTarget.victim); SocketConnection.Act("$n&n untangles $n&n.", ch, null, victim, SocketConnection.MessageTarget.everyone_but_victim); } else { ch.SendText("You untangle yourself.\r\n"); SocketConnection.Act("$n&n untangles $mself.", ch, null, null, SocketConnection.MessageTarget.room); } ch.PracticeSkill("untangle"); 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; }
/// <summary> /// Eat something. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Eat(CharData ch, string[] str) { if( ch == null ) return; Object obj; if (ch.IsBlind()) return; if (ch.Fighting || ch.CurrentPosition == Position.fighting) { ch.SendText("You can't eat while you're fighting!\r\n"); return; } if (str.Length == 0) { ch.SendText("Eat what?\r\n"); return; } if (!(obj = ch.GetObjCarrying(str[0]))) { ch.SendText("You do not have that item.\r\n"); return; } if (!ch.IsImmortal()) { if (obj.ItemType != ObjTemplate.ObjectType.food && obj.ItemType != ObjTemplate.ObjectType.pill) { ch.SendText("That's not edible.\r\n"); return; } if (!ch.IsNPC() && ((PC)ch).Hunger > 40) { ch.SendText("You are too full to eat more.\r\n"); return; } } SocketConnection.Act("You consume $p&n.", ch, obj, null, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n inhales $p&n.", ch, obj, null, SocketConnection.MessageTarget.room); switch (obj.ItemType) { case ObjTemplate.ObjectType.food: if (!ch.IsNPC()) { int condition = ((PC)ch).Hunger; if (!ch.IsUndead()) { ch.AdjustHunger(obj.Values[0]); } if (((PC)ch).Hunger > 40) { ch.SendText("You are full.\r\n"); } else if (condition == 0 && ((PC)ch).Hunger > 0) { ch.SendText("You are no longer hungry.\r\n"); } } if (obj.Values[3] != 0 && !CharData.CheckImmune(ch, Race.DamageType.poison)) { /* The shit was poisoned! */ Affect af = new Affect(); SocketConnection.Act("$n chokes and gags.", ch, null, null, SocketConnection.MessageTarget.room); ch.SendText("You choke and gag.\r\n"); af.Type = Affect.AffectType.spell; af.Value = "poison"; af.Duration = 2 * obj.Values[0]; af.AddModifier(Affect.Apply.strength, -(obj.Level / 7 + 2)); af.SetBitvector(Affect.AFFECT_POISON); ch.CombineAffect(af); } break; case ObjTemplate.ObjectType.pill: { for (int i = 1; i <= 4; i++) { String spellName = SpellNumberToTextMap.GetSpellNameFromNumber(obj.Values[i]); if (String.IsNullOrEmpty(spellName)) { Log.Error("Eat: Spell number " + obj.Values[i] + " not found for pill object " + obj.ObjIndexNumber + ". Make sure it's in the SpellNumberToTextMap."); } Spell spell = StringLookup.SpellLookup(spellName); if (!spell) { Log.Error("Eat: Spell '" + spellName + "' not found for pill object " + obj.ObjIndexNumber + ". Make sure it's in the spells file."); } else { spell.Invoke(ch, obj.Values[0], ch); } } } break; } if (!ch.IsNPC() || (ch.IsNPC() && ch.IsAffected(Affect.AFFECT_CHARM))) { obj.RemoveFromWorld(); } return; }
public static void Chameleon(CharData ch, string[] str) { if( ch == null ) return; if (!ch.IsNPC() && !ch.HasSkill("chameleon power")) { ch.SendText("You don't know how to act like a chameleon.\r\n"); return; } ch.SendText("You attempt to blend in with your surroundings.\r\n"); if (ch.IsAffected(Affect.AFFECT_HIDE)) { ch.RemoveAffect(Affect.AFFECT_HIDE); } if (ch.CheckSkill("chameleon power")) { ch.SetAffectBit(Affect.AFFECT_HIDE); } return; }
/// <summary> /// Shows a character's attribute screen. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Attributes(CharData ch, string[] str) { if( ch == null ) return; string buf1 = String.Empty; if (ch.IsNPC()) { ch.SendText("&nYour attributes are as would be expected for an NPC.\r\n"); return; } if (ch.IsImmortal() && str.Length != 0) { CharData worldChar = ch.GetCharWorld(str[0]); if (!worldChar) { ch.SendText("No such person.\r\n"); return; } if (worldChar.IsNPC()) { ch.SendText("NPCs don't have skills!\r\n"); return; } } string buf = String.Format( "&+WName: &+G{0}&n &+WLevel: {1}&n\r\n", MUDString.PadStr(ch.Name, 17), ch.Level); buf1 += buf; buf = String.Format( "&+WRace:&n {0} &+WClass:&n {1} &n&+WSex:&n {2}\r\n", MUDString.PadStr(Race.RaceList[ch.GetRace()].ColorName, 16), MUDString.PadStr(ch.CharacterClass.WholistName, 16), System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase(ch.GetSexString())); buf1 += buf; // Break a player's size into strings when we get around to it // -- Xangis if (!ch.IsNPC()) { buf = String.Format( "&+WHeight:&n {0} inches &+WWeight:&n {1} pounds &+WSize:&n {2}\r\n", MUDString.PadInt(((PC)ch).Height, 3), MUDString.PadInt(((PC)ch).Weight, 5), Race.SizeString(ch.CurrentSize)); } else { buf = String.Format("&+WSize:&n {0}\r\n", ch.CurrentSize); } buf1 += buf; TimeSpan time = TimeSpan.FromTicks(ch.TimePlayed.Ticks) + (DateTime.Now - ch.LogonTime); int days = (int)time.TotalHours / 24; time = (time - TimeSpan.FromDays(days)); int hours = (int)time.TotalHours; time = (time - TimeSpan.FromHours(hours)); int minutes = (int)time.TotalMinutes; // Age is a hack until we get it coded - Xangis buf = String.Format( "\r\n&+BAge:&n {0} years. &+BPlaying Time:&n {1} days {2} hours {3} minutes.\r\n", MUDString.PadInt(ch.GetAge(), 3), days, hours, minutes); buf1 += buf; // Need to create a function to display character status strings buf = String.Format("&+BStatus:&n {0}", System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase(Position.PositionString(ch.CurrentPosition))); if (!ch.IsNPC() && ch.IsAffected(Affect.AFFECT_BERZERK)) { buf += ", &+Rberzerk&n"; } if (!ch.IsNPC() && ch.HasActionBit(PC.PLAYER_MEMORIZING)) { buf += ", Memorizing"; } if (ch.IsAffected(Affect.AFFECT_CASTING)) { buf += ", Casting"; } if (ch.IsAffected(Affect.AFFECT_SINGING)) { buf += ", Singing"; } if (!ch.IsNPC() && ch.HasActionBit(PC.PLAYER_MEDITATING)) { buf += ", Meditating"; } if (!ch.IsNPC() && ch.HasActionBit(PC.PLAYER_CAMPING)) { /* This is ugly and should be moved to its own function */ buf += ", Camping"; } buf += ".\r\n\r\n"; buf1 += buf; // We want players to see the same stats for levels 1-50. // Should create string converters so that we have no decimals displayed // below this point. buf = String.Format(" &+cSTR:&n {0} &+cArmor Class:&n {1}.\r\n", MUDString.PadStr(StringConversion.AbilityScoreString(ch.GetCurrStr()), 15), ch.GetAC()); buf1 += buf; buf = String.Format(" &+cAGI:&n {0} &+cHitroll:&n {1}\r\n", MUDString.PadStr(StringConversion.AbilityScoreString(ch.GetCurrAgi()), 15), StringConversion.BonusString(ch.GetHitroll(ObjTemplate.WearLocation.hand_one))); buf1 += buf; buf = String.Format(" &+cDEX:&n {0} &+cDamroll:&n {1}\r\n", MUDString.PadStr(StringConversion.AbilityScoreString(ch.GetCurrDex()), 15), StringConversion.BonusString(ch.GetDamroll(ObjTemplate.WearLocation.hand_one))); buf1 += buf; buf = String.Format(" &+cCON:&n {0} &+cAlignment:&n {1}\r\n", MUDString.PadStr(StringConversion.AbilityScoreString(ch.GetCurrCon()), 15), StringConversion.AlignmentString(ch)); buf1 += buf; buf = String.Format(" &n&+cINT:&n {0}\r\n", MUDString.PadStr(StringConversion.AbilityScoreString(ch.GetCurrInt()), 15)); buf1 += buf; buf = String.Format(" &+cWIS:&n {0} &+BSaving Throws&n\r\n", MUDString.PadStr(StringConversion.AbilityScoreString(ch.GetCurrWis()), 15)); buf1 += buf; buf = String.Format(" &+cPOW:&n {0} &+cParalysis:&n {1}\r\n", MUDString.PadStr(StringConversion.AbilityScoreString(ch.GetCurrPow()), 15), StringConversion.BonusString(-ch.SavingThrows[0])); buf1 += buf; buf = String.Format(" &+cCHA:&n {0} &+cRod:&n {1}\r\n", MUDString.PadStr(StringConversion.AbilityScoreString(ch.GetCurrCha()), 15), StringConversion.BonusString(-ch.SavingThrows[1])); buf1 += buf; buf = String.Format(" &+cLUK:&n {0} &+cPetrify:&n {1}\r\n", MUDString.PadStr(StringConversion.AbilityScoreString(ch.GetCurrLuck()), 15), StringConversion.BonusString(-ch.SavingThrows[2])); buf1 += buf; buf = String.Format(" &+cBreath:&n {0}\r\n", StringConversion.BonusString(-ch.SavingThrows[3])); buf1 += buf; buf = String.Format("&+BWimpy: &n{0} &+cSpell:&n {1}\r\n", MUDString.PadInt(ch.Wimpy, 4), StringConversion.BonusString(-ch.SavingThrows[4])); buf1 += buf; buf = String.Format("&+BLoad Carried: &n{0} pounds ({1})\r\n", MUDString.PadInt(ch.CarryWeight, 3), StringConversion.WeightString(ch)); buf1 += buf; ch.SendText(buf1); return; }
/// <summary> /// Circle around behind someone and backstab them. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Circle(CharData ch, string[] str) { if( ch == null ) return; CharData victim; /* Verify that ch can circle. */ if (!ch.IsNPC() && !ch.HasSkill("circle")) { ch.SendText("You'd better leave the assassination trade to those more skilled.\r\n"); return; } /* No charmies or NPC's are allowed to circle. */ if (ch.IsNPC() && ch.IsAffected(Affect.AFFECT_CHARM)) { return; } /* Yeah, gallop around them without them noticing. */ if (ch.Riding) { ch.SendText("You can't circle while mounted.\r\n"); return; } /* Find the unlucky soul. */ if (str.Length == 0) { victim = ch.Fighting; } else { if (!(victim = ch.GetCharRoom(str[0]))) { ch.SendText("They aren't here.\r\n"); return; } } /* No target. */ if (!victim) { ch.SendText("Circle who?\r\n"); return; } /* Run around yourself? Ok. */ if (victim == ch) { ch.SendText("You spin around in a circle. Whee!\r\n"); return; } /* Check for protection of victim. */ victim = Combat.CheckGuarding(ch, victim); if (Combat.IsSafe(ch, victim)) { return; } // is_safe could wipe out victim, as it calls procs if a boss // check and see that victim is still valid if (!victim) { return; } /* Check if someone is attacking ch. */ CharData roomChar = null; foreach (CharData irch in ch.InRoom.People) { if (irch.Fighting == ch) { roomChar = irch; break; } } if (roomChar) { ch.SendText("You're too busy being hit right now.\r\n"); return; } Object obj = Object.GetEquipmentOnCharacter(ch, ObjTemplate.WearLocation.hand_one); if (!obj || obj.Values[3] != 11) { ch.SendText("You need to wield a piercing weapon.\r\n"); return; } SocketConnection.Act("You circle around behind $N&n...", ch, null, victim, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n circles around behind $N&n...", ch, null, victim, SocketConnection.MessageTarget.room_vict); Crime.CheckAttemptedMurder(ch, victim); ch.WaitState(Skill.SkillList["circle"].Delay); if (ch.IsNPC() || MUDMath.NumberPercent() < ((PC)ch).SkillAptitude["circle"] + ch.GetCurrAgi() - victim.GetCurrAgi()) { /* Don't always switch. */ if (MUDMath.NumberPercent() < 40) { Combat.StopFighting(victim, false); } Combat.SingleAttack(ch, victim, "circle", ObjTemplate.WearLocation.hand_one); } else { SocketConnection.Act("You failed to get around $M!", ch, null, victim, SocketConnection.MessageTarget.character); } ch.PracticeSkill("circle"); return; }
/// <summary> /// Flee: Attempt to run away from combat. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Flee(CharData ch, string[] str) { if( ch == null ) return; int attempt; int chances; if (ch.CurrentPosition < Position.reclining || ch.Wait > 0) { return; } // Remove memorization and meditation bits - Xangis if (!ch.IsNPC() && ch.HasActionBit(PC.PLAYER_MEDITATING)) { SocketConnection.Act("$N&n is disrupted from meditation.", ch, null, null, SocketConnection.MessageTarget.room); SocketConnection.Act("Your meditation is disrupted.", ch, null, null, SocketConnection.MessageTarget.character); ch.RemoveActionBit(PC.PLAYER_MEDITATING); } if (!ch.IsNPC() && ch.HasActionBit(PC.PLAYER_MEMORIZING)) { SocketConnection.Act("$N&n abandons $S studies.", ch, null, null, SocketConnection.MessageTarget.room); SocketConnection.Act("You abandon your studies.", ch, null, null, SocketConnection.MessageTarget.character); ch.RemoveActionBit(PC.PLAYER_MEMORIZING); } if (ch.CurrentPosition < Position.fighting) { ch.SendText("You scramble madly to your feet!\r\n"); SocketConnection.Act("$n&n scrambles madly to $s feet!", ch, null, null, SocketConnection.MessageTarget.room); ch.CurrentPosition = Position.standing; return; } if (!ch.InRoom) { ch.SendText("You give up when you realize there's nowhere to flee to.\r\n"); } // Panicked people can flee when not fighting. CharData victim = ch.Fighting; if (!victim) { if (ch.CurrentPosition == Position.fighting) { ch.CurrentPosition = Position.standing; } } if (ch.IsAffected(Affect.AFFECT_BERZERK)) { ch.SendText("You can't flee, you're in a &+RBl&n&+ro&+Ro&n&+rd&+L Rage&n!!\r\n"); return; } if (ch.IsAffected( Affect.AFFECT_BOUND)) { ch.SendText("You are bound! You can't move!\r\n"); SocketConnection.Act("$n&n tries to flee, but is tied up!", ch, null, null, SocketConnection.MessageTarget.room); return; } if (ch.IsAffected( Affect.AFFECT_HOLD) || ch.IsAffected( Affect.AFFECT_MINOR_PARA)) { ch.SendText("You can't move!\r\n"); SocketConnection.Act("$n&n tries to flee, but $e can't move!", ch, null, null, SocketConnection.MessageTarget.room); return; } // You should almost always be able to flee when not fighting. if (ch.CurrentPosition == Position.standing) { chances = 30; } else { chances = 6; } Room wasIn = ch.InRoom; for (attempt = 0; attempt < chances; attempt++) { Exit exit; Exit.Direction door = Database.RandomDoor(); if ((exit = wasIn.GetExit(door)) == null || !exit.TargetRoom || exit.TargetRoom == wasIn || exit.HasFlag(Exit.ExitFlag.closed) || (ch.IsNPC() && (Room.GetRoom(exit.IndexNumber).HasFlag(RoomTemplate.ROOM_NO_MOB) || (ch.HasActionBit(MobTemplate.ACT_STAY_AREA) && exit.TargetRoom.Area != ch.InRoom.Area)))) { continue; } if (ch.Riding && ch.Riding.Fighting) { Combat.StopFighting(ch.Riding, true); } // Just to keep the damned messages from being wacky... ch.SetAffectBit(Affect.AFFECT_IS_FLEEING); ch.Move(door); ch.RemoveAffect(Affect.AFFECT_IS_FLEEING); if (ch.InRoom == wasIn) { break; } Room nowIn = ch.InRoom; ch.InRoom = wasIn; SocketConnection.Act("$n&n panics and attempts to flee...", ch, null, null, SocketConnection.MessageTarget.room, true); string text; if (ch.CheckSneak()) { SocketConnection.Act("$n&n has fled!", ch, null, null, SocketConnection.MessageTarget.room); } else { text = String.Format("$n&n flees {0}ward.", door.ToString()); SocketConnection.Act(text, ch, null, null, SocketConnection.MessageTarget.room, true); } ch.InRoom = nowIn; text = String.Format("You flee {0}ward!\r\n", door.ToString()); ch.SendText(text); Combat.StopFighting(ch, true); return; } SocketConnection.Act("$n&n tries to flee but can't make it out of here!", ch, null, null, SocketConnection.MessageTarget.room, true); ch.SendText("&+WYour escape is blocked!\r\n"); return; }
/// <summary> /// Ask: Primarily used for quest files, but can be used in regular conversation too. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Ask(CharData ch, string[] str) { if( ch == null ) return; QuestTemplate quest; if (str.Length < 2) { ch.SendText("Ask who what?\r\n"); return; } CharData victim = ch.GetCharRoom(str[0]); if (!victim) { ch.SendText("They're not here.\r\n"); return; } if (ch.IsAffected( Affect.AFFECT_MUTE) || ch.HasInnate(Race.RACE_MUTE) || ch.InRoom.HasFlag(RoomTemplate.ROOM_SILENT)) { ch.SendText("Your lips move but nothing escapes their bounds.\r\n"); return; } string text = String.Join(" ", str, 1, (str.Length - 1)); text = DrunkSpeech.MakeDrunk(text, ch); SocketConnection.Act("$n&n asks $N&n a question.", ch, null, victim, SocketConnection.MessageTarget.everyone_but_victim); string buf = String.Format("&n&+c$n&n&+c asks you '&+c{0}&n&+c'&n", text); SocketConnection.Act(buf, ch, null, victim, SocketConnection.MessageTarget.victim); buf = String.Format("&n&+cYou ask $N&n&+c '{0}&n&+c'&n", text); SocketConnection.Act(buf, ch, null, victim, SocketConnection.MessageTarget.character); // players can't have talk files -- go home! if (!victim.IsNPC()) return; bool questfound = false; foreach (QuestTemplate it in QuestTemplate.QuestList) { quest = it; if (quest.Messages == null || (quest.IndexNumber != victim.MobileTemplate.IndexNumber)) continue; foreach (TalkData message in quest.Messages) { if (MUDString.NameContainedIn(text, message.Keywords)) { ch.SendText("\r\n"); ch.SendText(message.Message); questfound = true; } } } // Only check chatterbot responses when there isn't a quest with the same keywords. if (!questfound && victim.ChatBot != null) { victim.ChatBot.CheckConversation(victim, ch, text); } return; }
/// <summary> /// Command to follow someone. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Follow(CharData ch, string[] str) { if( ch == null ) return; if (str.Length == 0) { ch.SendText("Follow whom?\r\n"); return; } CharData victim = ch.GetCharRoom(str[0]); if (!victim) { ch.SendText("They aren't here.\r\n"); return; } if (ch.IsAffected(Affect.AFFECT_CHARM) && ch.Master) { SocketConnection.Act("But you'd rather follow $N&n!", ch, null, ch.Master, SocketConnection.MessageTarget.character); return; } if (victim.Master == ch) { ch.SendText("No following in loops!\r\n"); return; } if (victim == ch) { if (!ch.Master) { ch.SendText("You already follow yourself.\r\n"); return; } Combat.StopFighting(ch, true); return; } if (ch.Master) { Combat.StopFighting(ch, true); } // This sets following state and then sends a "you now follow" message to the follower. CharData.AddFollower(ch, victim); return; }
/// <summary> /// Knock the weapon from an opponent's hand. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Disarm(CharData ch, string[] str) { if( ch == null ) return; int odds; /* Don't allow charmed mobiles to do this, check player's level */ if ((ch.IsNPC() && ch.IsAffected( Affect.AFFECT_CHARM)) || (!ch.IsNPC() && !ch.HasSkill("disarm"))) { ch.SendText("You don't know how to disarm opponents.\r\n"); return; } if (!Object.GetEquipmentOnCharacter(ch, ObjTemplate.WearLocation.hand_one) && !Object.GetEquipmentOnCharacter(ch, ObjTemplate.WearLocation.hand_two)) { ch.SendText("You must wield a weapon to disarm.\r\n"); return; } if (!ch.Fighting) { ch.SendText("You aren't fighting anyone.\r\n"); return; } CharData victim = ch.Fighting; if (str.Length != 0) { if (!(victim = ch.GetCharRoom(str[0]))) { ch.SendText("They aren't here.\r\n"); return; } } if (victim.Fighting != ch && ch.Fighting != victim) { SocketConnection.Act("$E is not fighting you!", ch, null, victim, SocketConnection.MessageTarget.character); return; } if (!Object.GetEquipmentOnCharacter(victim, ObjTemplate.WearLocation.hand_one) && !Object.GetEquipmentOnCharacter(victim, ObjTemplate.WearLocation.hand_two)) { ch.SendText("Your opponent is not wielding a weapon.\r\n"); return; } if (victim.Level > ch.Level + 10) { ch.SendText("They are much too clever for such a clumsy attempt at that maneuver.\r\n"); return; } ch.WaitState(Skill.SkillList["disarm"].Delay); ch.PracticeSkill("disarm"); if (ch.IsNPC()) { odds = ch.Level; } else { odds = ((PC)ch).SkillAptitude["disarm"] / 2; } if (victim.IsNPC()) { odds += 2 * (ch.Level - victim.Level); } else { /* Offense skill helps prevent disarms */ odds -= ((PC)victim).SkillAptitude["offense"] / 4; } if (!Object.GetEquipmentOnCharacter(ch, ObjTemplate.WearLocation.hand_one)) { odds /= 2; /* 1/2 as likely with only 2nd weapon */ } odds = Math.Min(odds, 98); odds = Math.Max(odds, 2); string lbuf = String.Format("Disarm: {0} attempting with {1}%% chance.", ch.Name, odds); ImmortalChat.SendImmortalChat(null, ImmortalChat.IMMTALK_SPAM, 0, lbuf); if (MUDMath.NumberPercent() < odds) { Combat.Disarm(ch, victim); } else if (MUDMath.NumberPercent() > 80) { ch.SendText("Expertly countering your maneuver, they dislodge your weapon and send it flying.\r\n"); Combat.Disarm(victim, ch); } else { ch.SendText("You failed in your attempt.\r\n"); } return; }
/// <summary> /// Bash. Usable to initiate combat and during combat. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Bash(CharData ch, string[] str) { if( ch == null ) return; int chance; /* Check player's level and class, mobs can use this skill */ if ((!ch.HasSkill("bash"))) { ch.SendText("You'd better leave that to those with more skills.\r\n"); return; } if (ch.IsBlind() && !ch.Fighting) { return; } /* Verify a target. */ CharData victim = ch.Fighting; if (str.Length != 0) { victim = ch.GetCharRoom(str[0]); if (!victim || victim.CurrentPosition == Position.dead) { ch.SendText("They aren't anywhere to be found.\r\n"); return; } } else { if (!victim || victim.CurrentPosition == Position.dead) { ch.SendText("You aren't fighting anyone.\r\n"); return; } } /* Bash self? Ok! */ // Toned down the damage cuz you can't really bash yourself // like you could with someone else. if (victim == ch) { ch.SendText("You throw yourself to the ground!\r\n"); SocketConnection.Act("$N&n knocks $mself to the ground.", ch, null, victim, SocketConnection.MessageTarget.room_vict); ch.CurrentPosition = Position.kneeling; ch.WaitState((Skill.SkillList["bash"].Delay * 8) / 10); Combat.InflictDamage(ch, ch, MUDMath.NumberRange(1, 3), "bash", ObjTemplate.WearLocation.none, AttackType.DamageType.bludgeon); return; } /* Check size of ch vs. victim. */ /* If ch is too small. */ if (ch.CurrentSize < victim.CurrentSize) { SocketConnection.Act("$N&n is too big for you to bash!", ch, null, victim, SocketConnection.MessageTarget.character); return; } /* Ch 2 or more sizes larger than victim => bad! */ if (ch.CurrentSize - 2 > victim.CurrentSize) { SocketConnection.Act("You nearly topple over as you try to bash $N&n.", ch, null, victim, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n nearly topples over as $e attempts to bash you.", ch, null, victim, SocketConnection.MessageTarget.victim); SocketConnection.Act("$n&n nearly topples over as $e attempts to bash $N&n.", ch, null, victim, SocketConnection.MessageTarget.room_vict); ch.WaitState((Skill.SkillList["bash"].Delay)); ch.CurrentPosition = Position.kneeling; if (victim.Fighting == null) { Combat.SetFighting(victim, ch); } return; } /* Lag to basher from bash. Pets get more lag because pets are cheesy */ if (!ch.IsNPC()) { ch.WaitState(MUDMath.FuzzyNumber(Skill.SkillList["bash"].Delay)); } else { ch.WaitState((Skill.SkillList["bash"].Delay * 6 / 5)); } /* Base chance to bash, followed by chance modifications. */ if (ch.IsNPC()) { chance = (ch.Level * 3) / 2 + 15; } else { chance = ((PC)ch).SkillAptitude["bash"] - 5; } if (victim.CurrentPosition < Position.fighting) { chance /= 5; //used to be 0 } else { chance += ch.GetCurrAgi() - victim.GetCurrAgi(); } if (chance > 95) { chance = 95; } Object obj = Object.GetEquipmentOnCharacter(ch, ObjTemplate.WearLocation.hand_one); if (!obj) { /* No primary item. */ if (!(obj = Object.GetEquipmentOnCharacter(ch, ObjTemplate.WearLocation.hand_two))) { /* No items in hand. */ if (!ch.IsClass(CharClass.Names.paladin) && !ch.IsClass(CharClass.Names.antipaladin)) { if (!ch.IsClass(CharClass.Names.warrior)) { chance -= 25; } else { chance -= 20; } ch.SendText("You lower your shoulder and attempt to bash without a shield...\r\n"); } else { chance -= 3; // Hidden penalty for not having a shield } } else if (obj.ItemType != ObjTemplate.ObjectType.shield) { /* Secondary item isn't a shield, no primary. */ if (!ch.IsClass(CharClass.Names.paladin) && !ch.IsClass(CharClass.Names.antipaladin)) { if (!ch.IsClass(CharClass.Names.warrior)) { chance -= 25; } else { chance -= 20; } ch.SendText("Bashing without a shield is tough, but you try anyway...\r\n"); } else { chance -= 5; // Small hidden penalty for not having a shield } } /* Secondary item is a shield, no primary. */ else if (ch.IsClass(CharClass.Names.paladin) || ch.IsClass(CharClass.Names.antipaladin)) { chance += 3; // Small hidden bonus for having a shield } } else if (obj.ItemType != ObjTemplate.ObjectType.shield) { /* Primary item isn't a shield. */ if (!(obj = Object.GetEquipmentOnCharacter(ch, ObjTemplate.WearLocation.hand_two))) { /* No secondary. */ if (!ch.IsClass(CharClass.Names.paladin) && !ch.IsClass(CharClass.Names.antipaladin)) { if (!ch.IsClass(CharClass.Names.warrior)) { chance -= 25; } else { chance -= 20; } ch.SendText("Without a shield, bashing is a wistful thought, but you try anyway...\r\n"); } else { chance -= 5; // Hidden penalty for not having a shield } } else if (obj.ItemType != ObjTemplate.ObjectType.shield) { /* Secondary item is not a shield. */ if (!ch.IsClass(CharClass.Names.paladin) && !ch.IsClass(CharClass.Names.antipaladin)) { if (!ch.IsClass(CharClass.Names.warrior)) { chance -= 25; } else { chance -= 20; } ch.SendText("Without a shield, your shoulder bash is but wishful thinking...\r\n"); } else { chance -= 5; // Hidden penalty for not having a shield } } else if (ch.IsClass(CharClass.Names.paladin) || ch.IsClass(CharClass.Names.antipaladin)) { /* Secondary is a shield. */ chance += 3; // Small hidden bonus for having a shield } else if (ch.IsClass(CharClass.Names.ranger)) { chance -= 8; } else if (ch.IsClass(CharClass.Names.warrior)) { chance -= 5; } } // Centaurs are awful damned hard to bash -- Xangis if (victim.GetRace() == Race.RACE_CENTAUR) { chance -= 25; } // damned high penalty for bashing blind if (ch.IsAffected(Affect.AFFECT_BLIND) && !victim.IsAffected(Affect.AFFECT_BLIND)) { chance /= 10; } if (ch.IsAffected(Affect.AFFECT_BLIND) && victim.IsAffected(Affect.AFFECT_BLIND)) { chance /= 4; } ch.PracticeSkill("bash"); /* Start a fight if not already in one. */ if (ch != victim) { if (!ch.Fighting) { Combat.SetFighting(ch, victim); } if (!victim.Fighting) { Combat.SetFighting(victim, ch); } } string lbuf = "Bash: " + ch.Name + " bashing " + victim.Name + " with " + chance + " chance."; ImmortalChat.SendImmortalChat(null, ImmortalChat.IMMTALK_SPAM, 0, lbuf); /* Do the bash, deal the damage. */ if (MUDMath.NumberPercent() < chance) { /* Hit the bash. */ if (victim.IsAffected(Affect.AFFECT_SINGING)) { victim.RemoveAffect(Affect.AFFECT_SINGING); SocketConnection.Act("$n&n chokes on a note and falls silent as $e slams into the ground!", victim, null, null, SocketConnection.MessageTarget.room); victim.SendText("You abort your singing!\r\n"); } if (victim.IsAffected(Affect.AFFECT_CASTING)) { victim.RemoveAffect(Affect.AFFECT_CASTING); SocketConnection.Act("$n&n's eyes roll back in $s head and $e forgets all about $s spell.", victim, null, null, SocketConnection.MessageTarget.room); victim.SendText("Being knocked over so forcefully makes it hard to cast.\r\n"); } if (!Combat.CheckTumble(victim)) { victim.WaitState(((Skill.SkillList["bash"].Delay * 5) / 6)); if (victim.CurrentPosition > Position.kneeling) { victim.CurrentPosition = Position.kneeling; } victim.SendText("You are knocked to the ground!\r\n"); Combat.InflictDamage(ch, victim, MUDMath.NumberRange(1, ch.Level), "bash", ObjTemplate.WearLocation.none, AttackType.DamageType.bludgeon); } else { Combat.InflictDamage(ch, victim, MUDMath.NumberRange(1, (ch.Level / 3)), "bash", ObjTemplate.WearLocation.none, AttackType.DamageType.bludgeon); victim.SendText("You roll with the blow, finally landing on your feet.\r\n"); SocketConnection.Act("$n&n rolls with the blow, finally landing on $s feet.", victim, null, null, SocketConnection.MessageTarget.room); } } else { /* Miss the bash. */ SocketConnection.Act("As $N&n avoids your bash, you topple to the &n&+yground&n with a loud crash.", ch, null, victim, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n crashes to the &n&+yground&n as you sidestep $s bash.", ch, null, victim, SocketConnection.MessageTarget.victim); SocketConnection.Act("$n&n misses $s bash at $N&n and is driven to the &n&+yground&n.", ch, null, victim, SocketConnection.MessageTarget.room_vict); ch.CurrentPosition = Position.kneeling; } return; }
/// <summary> /// Used for dragging corpses into another room. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Drag(CharData ch, string[] str) { if( ch == null ) return; Object obj; Object obj2; if (ch.IsAffected( Affect.AFFECT_HOLD) || ch.IsAffected(Affect.AFFECT_MINOR_PARA)) { ch.SendText("You can't move!\r\n"); return; } if (str.Length == 0) { ch.SendText("Drag which what where?\r\n"); return; } if (str.Length == 0) { ch.SendText("You need to specify a direction.\r\n"); return; } if (!ch.IsNPC() && ch.HasActionBit(PC.PLAYER_MEMORIZING)) { ch.RemoveActionBit(PC.PLAYER_MEMORIZING); ch.SendText("You abandon your studies.\r\n"); } if (!(obj = ch.GetObjHere(str[0]))) { ch.SendText("You do not see that here.\r\n"); return; } if (obj.ItemType != ObjTemplate.ObjectType.npc_corpse && obj.ItemType != ObjTemplate.ObjectType.pc_corpse) { ch.SendText("You can only drag corpses.\r\n"); return; } if (str.Length > 2 && str[1] == "enter") { if ((obj2 = ch.GetObjHere(str[3]))) { switch (obj2.ItemType) { case ObjTemplate.ObjectType.teleport: case ObjTemplate.ObjectType.portal: if (obj2.ItemType == ObjTemplate.ObjectType.teleport && !CommandType.CheckCommandTrigger("enter", obj2.Values[1])) { ch.SendText("Nothing happens.\r\n"); return; }; Room location; if (Macros.IsSet(obj2.Values[3], ObjTemplate.PORTAL_RANDOM)) { location = Movement.GetRandomRoom(); } else { location = Room.GetRoom(obj2.Values[0]); } if (!location) { ch.SendText("That portal doesn't seem to go anywhere.\r\n"); return; } SocketConnection.Act("You drag the $p&n into $P&n.", ch, obj, obj2, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n drags the $p&n into $P&n.", ch, obj, obj2, SocketConnection.MessageTarget.room); if (obj2.Values[2] >= 0) { obj2.Values[2] -= 2; if (obj2.Values[2] <= 0) { SocketConnection.Act("$p&n fades into nothingness.", ch, obj2, null, SocketConnection.MessageTarget.room); obj2.RemoveFromRoom(); } } obj.RemoveFromRoom(); ch.RemoveFromRoom(); ch.AddToRoom(location); obj.AddToRoom(location); if (obj2.ItemType == ObjTemplate.ObjectType.portal) { SocketConnection.Act("$n&n steps out of $P&n dragging the $p&n.", ch, obj, obj2, SocketConnection.MessageTarget.room); } else { SocketConnection.Act("$n&n appears from elsewhere, dragging the $p&n.", ch, obj, null, SocketConnection.MessageTarget.room); } CommandType.Interpret(ch, "look auto"); return; case ObjTemplate.ObjectType.vehicle: case ObjTemplate.ObjectType.ship: break; case ObjTemplate.ObjectType.other: break; default: ch.SendText("That cannot be entered.\r\n"); return; } } } Exit.Direction door = Movement.FindExit(ch, str[1]); if (door < 0) { ch.SendText("You can't drag anything that way.\r\n"); return; } if (ch.CurrentMoves < 5 && !ch.IsImmortal()) { ch.SendText("You are too exhausted to drag that anywhere.\r\n"); return; } string text = String.Format("You drag $p&n {0}.", door.ToString()); SocketConnection.Act(text, ch, obj, null, SocketConnection.MessageTarget.character); text = String.Format("$n&n drags $p&n {0}.", door.ToString()); SocketConnection.Act(text, ch, obj, null, SocketConnection.MessageTarget.room); obj.RemoveFromRoom(); ch.CurrentMoves -= 5; ch.Move(door); ch.WaitState(MUDMath.NumberRange(3, 12)); obj.AddToRoom(ch.InRoom); SocketConnection.Act("$n&n drags $p&n along behind $m.", ch, obj, null, SocketConnection.MessageTarget.room); }
/// <summary> /// Place an object in your hand. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Hold(CharData ch, string[] str) { if( ch == null ) return; Object obj; if (ch.IsAffected( Affect.AFFECT_HOLD) || ch.IsAffected( Affect.AFFECT_MINOR_PARA)) { ch.SendText("You can't move!\r\n"); return; } if (!ch.IsNPC() && ch.IsAffected( Affect.AFFECT_WRAITHFORM)) { ch.SendText("You may not wear, wield, or hold anything in &+Wghoul&n form.\r\n"); return; } if (str.Length == 0 || (obj = ch.GetObjCarrying(str[0])) == null) { ch.SendText("Hold what now?\r\n"); return; } // Light items are automatically holdable. if (!obj.HasWearFlag(ObjTemplate.WEARABLE_HOLD) && obj.ItemType != ObjTemplate.ObjectType.light) { ch.SendText("You can't hold that!\r\n"); return; } if (obj.ItemType == ObjTemplate.ObjectType.weapon || obj.ItemType == ObjTemplate.ObjectType.ranged_weapon) { ch.SendText("You WIELD weapons, they're useless if you hold them.\r\n"); return; } if (!obj.IsWearableBy(ch)) return; if (Object.EquipInHand(ch, obj, Object.EQUIP_HOLD)) { SocketConnection.Act("You hold $p&n.", ch, obj, null, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n holds $p&n.", ch, obj, null, SocketConnection.MessageTarget.room); } return; }
/// <summary> /// Ingest a liquid. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Drink(CharData ch, string[] str) { if( ch == null ) return; Object obj = null; if (ch.IsBlind()) { return; } if (ch.Fighting || ch.CurrentPosition == Position.fighting) { ch.SendText("You can't drink while you're fighting!\r\n"); return; } if (str.Length == 0 && ch.InRoom != null) { foreach (Object iobj in ch.InRoom.Contents) { if (iobj.ItemType == ObjTemplate.ObjectType.drink_container) { obj = iobj; break; } } if (!obj) { ch.SendText("Drink what?\r\n"); return; } } else { if (!(obj = ch.GetObjHere(str[0]))) { ch.SendText("You can't find it.\r\n"); return; } } // Allow bards to get twice as drunk as other classes - Xangis if (!ch.IsNPC() && !ch.IsImmortal() && ((PC)ch).Drunk > 15 && ch.IsClass(CharClass.Names.bard) && MUDMath.NumberPercent() < ch.GetCurrAgi() - ((PC)ch).Drunk) { ch.SendText("You fail to reach your mouth. *Hic*\r\n"); return; } if (!ch.IsNPC() && !ch.IsImmortal() && ((PC)ch).Drunk > 25 && ch.IsClass(CharClass.Names.bard) && MUDMath.NumberPercent() < ch.GetCurrAgi() - ((PC)ch).Drunk) { ch.SendText("You fail to reach your mouth. *Hic*\r\n"); return; } switch (obj.ItemType) { default: ch.SendText("You can't drink from that.\r\n"); break; case ObjTemplate.ObjectType.drink_container: // -1 Means a container never goes empty. if (obj.Values[1] <= 0 && obj.Values[1] != -1) { ch.SendText("It is already &+Lempty&n.\r\n"); return; } /* No drinking if you're full */ if ((!ch.IsImmortal()) && ( (!ch.IsNPC() && ((PC)ch).Thirst > 40) || (!ch.IsNPC() && ((PC)ch).Hunger > 50))) { ch.SendText("You couldn't possibly drink any more.\r\n"); return; } int liquid; if ((liquid = obj.Values[2]) >= Liquid.Table.Length) { Log.Error("Drink: bad liquid number {0}.", liquid); liquid = obj.Values[2] = 0; } SocketConnection.Act("You drink $T from $p&n.", ch, obj, Liquid.Table[liquid].Name, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n drinks $T from $p&n.", ch, obj, Liquid.Table[liquid].Name, SocketConnection.MessageTarget.room); int amount = MUDMath.NumberRange(3, 10); if (obj.Values[0] != -1) { amount = Math.Min(amount, obj.Values[1]); } ch.AdjustDrunk(amount * Liquid.Table[liquid].DrunkValue); if (!ch.IsUndead()) { ch.AdjustHunger(amount * Liquid.Table[liquid].HungerValue); if (ch.IsAffected(Affect.AFFECT_THIRST)) { ch.AdjustThirst((amount * Liquid.Table[liquid].ThirstValue) / 12); ch.SendText("That doesn't taste as &+bwet&n as it used to.\r\n"); } else { ch.AdjustThirst(amount * Liquid.Table[liquid].ThirstValue); } } else { /* If blood */ if (Liquid.Table[liquid].Name == "blood") { ch.AdjustHunger(amount * 2); ch.AdjustThirst(amount); } } if (!ch.IsNPC() && ((PC)ch).Drunk > 10) { ch.SendText("You feel &n&+gdrunk&n.\r\n"); } if (!ch.IsNPC() && ((PC)ch).Hunger > 20) { ch.SendText("You are &n&+yfull&n.\r\n"); } if (!ch.IsNPC() && ((PC)ch).Thirst > 20) { ch.SendText("You do not feel &n&+cth&+Ci&n&+cr&+Cst&n&+cy&n.\r\n"); } if (obj.Values[3] != 0 && !CharData.CheckImmune(ch, Race.DamageType.poison)) { /* The shit was poisoned ! */ Affect af = new Affect(); ch.SendText("You choke and gag.\r\n"); SocketConnection.Act("$n chokes and gags.", ch, null, null, SocketConnection.MessageTarget.room); af.Type = Affect.AffectType.spell; af.Value = "poison"; af.Duration = 3 * amount; af.AddModifier(Affect.Apply.strength, -(obj.Level / 7 + 1)); af.SetBitvector(Affect.AFFECT_POISON); ch.CombineAffect(af); } /* HOLY_WATER and UNHOLY_WATER effects */ if ((ch.IsGood() && obj.Values[2] == 27) || (ch.IsEvil() && obj.Values[2] == 28)) { int heal = MUDMath.Dice(1, 8); if (ch.Hitpoints < ch.GetMaxHit()) { ch.Hitpoints = Math.Min(ch.Hitpoints + heal, ch.GetMaxHit()); ch.UpdatePosition(); ch.SendText("You feel a little better!\r\n"); } } if ((ch.IsEvil() && obj.Values[2] == 27) || (ch.IsGood() && obj.Values[2] == 28)) { int harm = MUDMath.Dice(1, 10); ch.Hitpoints = Math.Max(ch.Hitpoints - harm, -10); ch.SendText("You choke and feel as if you'd swallowed boiling oil!\r\n"); ch.UpdatePosition(); } /* End (UN)HOLY_WATER effects */ // -1 Means a container never goes empty. if (obj.Values[1] != -1) { obj.Values[1] -= amount; if (obj.Values[1] <= 0) { ch.SendText("The container is now &+Lempty&n.\r\n"); obj.Values[1] = 0; } } break; } return; }
/// <summary> /// Tracking code. /// </summary> /// <param name="ch"></param> public static void HuntVictim( CharData ch ) { if (!ch || !ch.Hunting || !ch.IsAffected(Affect.AFFECT_TRACK)) { return; } if( ch.CurrentPosition != Position.standing ) { if( ch.IsAffected( Affect.AFFECT_TRACK ) ) { ch.SendText( "You abort your tracking effort.\r\n" ); ch.RemoveAffect(Affect.AFFECT_TRACK); Combat.StopHunting( ch ); } return; } CharData tmp = null; try { /* * Make sure the victim still exists. */ bool found = false; foreach (CharData it in Database.CharList) { ch = it; if (ch.Hunting != null && ch.Hunting.Who == tmp) found = true; } if (!found || !CharData.CanSee(ch, ch.Hunting.Who)) { if (!ch.IsAffected(Affect.AFFECT_TRACK)) CommandType.Interpret(ch, "say Damn! My prey is gone!"); else { ch.SendText("The trail seems to disappear.\r\n"); ch.RemoveAffect(Affect.AFFECT_TRACK); } Combat.StopHunting(ch); return; } if (ch.InRoom == ch.Hunting.Who.InRoom) { if (ch.Fighting) { return; } FoundPrey(ch, ch.Hunting.Who); return; } ch.WaitState(Skill.SkillList["track"].Delay); Exit.Direction dir = FindPath(ch.InRoom.IndexNumber, ch.Hunting.Who.InRoom.IndexNumber, ch, -40000, true); if (dir == Exit.Direction.invalid) { if (!ch.IsAffected(Affect.AFFECT_TRACK)) { SocketConnection.Act("$n&n says 'Damn! Lost $M!'", ch, null, ch.Hunting.Who, SocketConnection.MessageTarget.room); } else { ch.SendText("You lose the trail.\r\n"); ch.RemoveAffect(Affect.AFFECT_TRACK); Combat.StopHunting(ch); } return; } /* * Give a random direction if the mob misses the die roll. */ if (MUDMath.NumberPercent() > 75) /* @ 25% */ { do { dir = Database.RandomDoor(); } while (!(ch.InRoom.ExitData[(int)dir]) || !(ch.InRoom.ExitData[(int)dir].TargetRoom)); } if (ch.InRoom.ExitData[(int)dir].HasFlag(Exit.ExitFlag.closed)) { CommandType.Interpret(ch, "open " + dir.ToString()); return; } ImmortalChat.SendImmortalChat(null, ImmortalChat.IMMTALK_HUNTING, 0, String.Format("{0}&n leaves room {1} to the {2}.", ch.ShortDescription, ch.InRoom.IndexNumber, dir.ToString())); if (ch.IsAffected(Affect.AFFECT_TRACK)) { SocketConnection.Act(String.Format("You sense $N&n's trail {0} from here...", dir.ToString()), ch, null, ch.Hunting.Who, SocketConnection.MessageTarget.character); } ch.Move(dir); if (ch.IsAffected(Affect.AFFECT_TRACK)) SocketConnection.Act("$n&n peers around looking for tracks.", ch, null, null, SocketConnection.MessageTarget.room); if (!ch.Hunting) { if (!ch.InRoom) { string text = String.Empty; text = String.Format("Hunt_victim: no ch.in_room! Mob #{0}, _name: {1}. Placing mob in limbo (ch.AddToRoom()).", ch.MobileTemplate.IndexNumber, ch.Name); Log.Error(text, 0); ch.AddToRoom(Room.GetRoom(StaticRooms.GetRoomNumber("ROOM_NUMBER_LIMBO"))); text = String.Format("{0}&n has gone to limbo while hunting {1}.", ch.ShortDescription, ch.Hunting.Name); ImmortalChat.SendImmortalChat(null, ImmortalChat.IMMTALK_HUNTING, 0, text); return; } CommandType.Interpret(ch, "say Damn! Lost my prey!"); return; } if (ch.InRoom == ch.Hunting.Who.InRoom) { FoundPrey(ch, ch.Hunting.Who); } return; } catch (Exception ex) { Log.Error("Exception in HuntVictim: " + ex.ToString()); } }
/// <summary> /// Drop an item. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Drop(CharData ch, string[] str) { if( ch == null ) return; Object cash; if (ch.IsAffected( Affect.AFFECT_HOLD) || ch.IsAffected( Affect.AFFECT_MINOR_PARA)) { ch.SendText("You muscles won't respond!\r\n"); return; } if (str.Length == 0) { ch.SendText("Drop what?\r\n"); return; } if (MUDString.IsNumber(str[0])) { /* 'drop NNNN coins' */ int amount; Int32.TryParse(str[0], out amount); if (amount <= 0) { ch.SendText("Sorry, you can't do that.\r\n"); return; } if (str.Length < 2) { ch.SendText("That's fine, but *what* do you want to drop?\r\n"); return; } if ("copper".StartsWith(str[1], StringComparison.CurrentCultureIgnoreCase)) { if (ch.GetCopper() < amount) { ch.SendText("You haven't got that many &n&+ycopper&n coins.\r\n"); return; } ch.SpendCopper(amount); cash = Object.CreateMoney(amount, 0, 0, 0); cash.AddToRoom(ch.InRoom); cash.FlyLevel = ch.FlightLevel; } else if ("silver".StartsWith(str[1], StringComparison.CurrentCultureIgnoreCase)) { if (ch.GetSilver() < amount) { ch.SendText("You haven't got that many &n&+wsilver&n coins.\r\n"); return; } ch.SpendSilver(amount); (Object.CreateMoney(0, amount, 0, 0)).AddToRoom(ch.InRoom); } else if ("gold".StartsWith(str[1], StringComparison.CurrentCultureIgnoreCase)) { if (ch.GetGold() < amount) { ch.SendText("You haven't got that many &+Ygold&n coins.\r\n"); return; } ch.SpendGold(amount); (Object.CreateMoney(0, 0, amount, 0)).AddToRoom(ch.InRoom); } else if ("platinum".StartsWith(str[1], StringComparison.CurrentCultureIgnoreCase)) { if (ch.GetPlatinum() < amount) { ch.SendText("You haven't got that many &+Wplatinum&n coins.\r\n"); return; } ch.SpendPlatinum(amount); (Object.CreateMoney(0, 0, 0, amount)).AddToRoom(ch.InRoom); } else { ch.SendText("They haven't minted that type of &+Lcoin&n yet.\r\n"); return; } /* Disabled merging of coin types. This should eventually be re-enabled for ( obj = ch.in_room.contents; obj; obj = obj_next ) { obj_next = obj.next_content; switch ( obj.pIndexData.vnum ) { case StaticObjects.OBJECT_NUMBER_MONEY_ONE: amount += 1; obj.ExtractFromWorld();; break; case StaticObjects.OBJECT_NUMBER_MONEY_SOME: amount += obj.value[0]; obj.ExtractFromWorld();; break; } } */ ch.SendText("Done.\r\n"); SocketConnection.Act("$n&n drops some &n&+wcoins&n.", ch, null, null, SocketConnection.MessageTarget.room); return; } if (str[0] != "all" && MUDString.IsPrefixOf("all.", str[0])) { /* 'drop iobj' */ Object iobj = ch.GetObjCarrying(str[0]); if (!iobj) { ch.SendText("You do not have that item.\r\n"); return; } if (!ch.CanDropObject(iobj)) { ch.SendText("You can't release your grip on it.\r\n"); return; } iobj.RemoveFromChar(); iobj.AddToRoom(ch.InRoom); // Prevent item duping - Xangis CharData.SavePlayer(ch); iobj.FlyLevel = ch.FlightLevel; SocketConnection.Act("You drop $p&n.", ch, iobj, null, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n discards $p&n.", ch, iobj, null, SocketConnection.MessageTarget.room); if (iobj.HasFlag(ObjTemplate.ITEM_TRANSIENT)) { SocketConnection.Act("$p&n crumbles to dust.", ch, iobj, null, SocketConnection.MessageTarget.all); iobj.RemoveFromWorld(); } else if (ch.InRoom.TerrainType == TerrainType.lava && !iobj.HasFlag(ObjTemplate.ITEM_NOBURN)) { SocketConnection.Act("$p&n melts as it sinks into the &+RLava&n.", ch, iobj, null, SocketConnection.MessageTarget.all); if (!ch.IsNPC()) { ((PC)ch).Destroyed.AddItem(iobj); } iobj.RemoveFromWorld(); } } else { /* 'drop all' or 'drop all.obj' */ bool found = false; for (int i = ch.Carrying.Count - 1; i >= 0 ; i--) { Object obj = ch.Carrying[i]; if ( (str.Length < 2 || MUDString.NameContainedIn(str[0].Substring(4), obj.Name)) && CharData.CanSeeObj(ch, obj) && obj.WearLocation == ObjTemplate.WearLocation.none && ch.CanDropObject(obj)) { found = true; obj.RemoveFromChar(); obj.AddToRoom(ch.InRoom); SocketConnection.Act("You drop $p&n.", ch, obj, null, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n drops $p&n.", ch, obj, null, SocketConnection.MessageTarget.room); if (obj.HasFlag(ObjTemplate.ITEM_TRANSIENT)) { SocketConnection.Act("$p&n crumbles to dust.", ch, obj, null, SocketConnection.MessageTarget.all); if (!ch.IsNPC()) { ((PC)ch).Destroyed.AddItem(obj); } obj.RemoveFromWorld(); } else if (ch.InRoom.TerrainType == TerrainType.lava && !obj.HasFlag(ObjTemplate.ITEM_NOBURN)) { SocketConnection.Act("$p&n melts as it sinks into the &+RLava&n.", ch, obj, null, SocketConnection.MessageTarget.all); if (!ch.IsNPC()) { ((PC)ch).Destroyed.AddItem(obj); } obj.RemoveFromWorld(); } } } if (!found) { if (str.Length > 1) { ch.SendText("You are not carrying anything."); } else { SocketConnection.Act("You are not carrying any $T&n.", ch, null, str[0].Substring(4), SocketConnection.MessageTarget.character); } } } return; }
// Checks for a mob spelling itself up. Certain spells have higher // priority and percentage chances. // // The spell_lookup _function is horribly inefficient and anywhere possible // should be replaced with _skillNumber's (Spell.SpellNumber_armor and whatever) - Xangis // // The commented out spells have not been written yet. // // The CheckSpellup _function automatically checks to see whether they // are effected by the particular spell, so unless the spell has an // associated bitvector, there is no need for extra logic. // // Spells with associated bitvectors will need the "CharData.IsAffected" stuff // before the if( CheckSpellup( ... ) ) for the particular spell static bool Spellup( CharData ch ) { if (ch == null) return false; if (ch.IsAffected(Affect.AFFECT_BLIND)) { if( CheckSpellup( ch, "purify spirit", 35 ) ) return true; } if( !ch.IsAffected( Affect.AFFECT_BLUR ) ) if( CheckSpellup( ch, "blur", 45 ) ) return true; /* Fireshield and Frostshield cancel eachother! So, we don't want * that to happen. Easiest way is to give a chance to try either. * Odds are, if they only have one of the two, that they'll take twice * as long to cast it on themselves. Yes, this is a quick fix. */ if( !ch.IsAffected( Affect.AFFECT_FIRESHIELD ) && !ch.IsAffected( Affect.AFFECT_COLDSHIELD ) ) { if( MUDMath.NumberPercent() < 50 ) { if( CheckSpellup( ch, "fireshield", 30 ) ) return true; } else if( CheckSpellup( ch, "coldshield", 30 ) ) return true; } if( CheckSpellup( ch, "vitality", 55 ) ) return true; return false; }
/// <summary> /// Innate mount summoning command for antipaladins and paladins. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void SummonMount(CharData ch, string[] str) { MobTemplate mobTemplate; Affect af = new Affect(); int mountNumber = ch.CharacterClass.CanSummonMountNumber; if (mountNumber == 0) { ch.SendText("You scream and yell for a mount. Strangely nothing comes.\r\n"); return; } if (ch.IsAffected( Affect.AFFECT_SUMMON_MOUNT_TIMER)) { ch.SendText("&nIt is too soon to accomplish that!\r\n"); return; } // Look to see if they already have a mount. foreach (CharData previousMount in Database.CharList) { if (previousMount.Master == ch && previousMount.IsNPC() && previousMount.MobileTemplate != null && (previousMount.MobileTemplate.IndexNumber == mountNumber)) { ch.SendText("You already have a mount!\r\n"); return; } } // If not let found, them summon one. mobTemplate = Database.GetMobTemplate(mountNumber); if (mobTemplate == null) { Log.Error("SummonMount: Invalid MobTemplate!", 0); return; } CharData mount = Database.CreateMobile(mobTemplate); // Simulate the poor mount running across the world. // They arrive with partially depleted moves. mount.CurrentMoves -= MUDMath.Dice(4, 40); CharData.AddFollower(mount, ch); mount.SetAffectBit(Affect.AFFECT_CHARM); mount.SetActionBit(MobTemplate.ACT_NOEXP); mount.AddToRoom(ch.InRoom); ch.WaitState(MUDMath.FuzzyNumber(Skill.SkillList["summon mount"].Delay)); SocketConnection.Act("$n&n trots up to you.", mount, null, ch, SocketConnection.MessageTarget.victim); SocketConnection.Act("$n&n trots up to $N&n.", mount, null, ch, SocketConnection.MessageTarget.everyone_but_victim); if (ch.IsImmortal()) { return; } af.Value = "summon mount"; af.Type = Affect.AffectType.skill; af.Duration = 48; af.SetBitvector(Affect.AFFECT_SUMMON_MOUNT_TIMER); ch.AddAffect(af); return; }