/* Like Handletake, HandleDrop checks for an item's existence, but in this case it has to be in the * requesting user's inventory. * if item exists, remove it from the user inventory's list of refs and add to the room's Items instead */ void HandleDrop(User sender, string e) { if (sender.Player.IsDead) { sender.Connection.SendMessage("You cannot do that while defeated!"); return; } int roomId = CommandUtils.GetCurrentRoomId(sender, Map); Item target = sender.Inventory.Items.FirstOrDefault(t => CommandUtils.FuzzyEquals(t.Name, e)); if (target == null) { HandleHoldDrop(sender, e); return; } if (!target.Commands.Contains("drop")) { sender.Connection.SendMessage("You cannot drop that."); return; } XMLReference <Item> item = new XMLReference <Item> { Actual = target }; sender.Player.Drop(target); sender.Inventory.setCurrentLoweredCapacity(target.Weight); sender.Inventory.RemoveFromInventory(target); Map.Rooms[roomId].Items.Add(item); }
// RoomSay handles sending a message to all Users within a Room // Semantically this is the same as Broadcast, but with the exception that it only sends to players whose CurrRoomId's match the speaker's. public void RoomSay(string msg, User sender) { lock (Users) { foreach (User user in Users) { if (CommandUtils.GetCurrentRoomId(user, Map) == CommandUtils.GetCurrentRoomId(sender, Map)) { user.Connection.SendMessage(msg); } } } }
void HandleContainerExamine(User sender, string e) { int roomId = CommandUtils.GetCurrentRoomId(sender, Map); Container container = Map.Rooms[roomId].Containers.FirstOrDefault(t => CommandUtils.FuzzyEquals(t.Actual.Name, e))?.Actual; if (container == null) { // If it's not an npc, item, or container, it's unexaminable sender.Connection.SendMessage("That does not exist here!"); return; } sender.Connection.SendMessage($"You examine the {e}."); sender.Connection.SendMessage($"{container.Description}"); }
/* HandleExamine allows a user to examine an object or themselves * 'examine self' returns a description of the user's player npc, including what they're wearing and appearance. * 'examine <item>' returns the description of the item. The item can be either in the room or in the user's inventory. * If the item is in neither, there is no description. */ void HandleExamine(User sender, string e) { if (sender.Player.IsDead) { sender.Connection.SendMessage("You cannot do that while defeated!"); return; } if (e == null) { sender.Connection.SendMessage("Examine what?"); return; } if (CommandUtils.FuzzyEquals(e, "self")) { sender.Connection.SendMessage("You look yourself over."); if (sender.Player.Equipped.Count > 0) { sender.Connection.SendMessage($"Equipped: {string.Join(", ", sender.Player.Equipped)}"); } if (sender.Player.Held.Count > 0) { sender.Connection.SendMessage($"Held: {string.Join(", ", sender.Player.Held)}"); } sender.Connection.SendMessage($"Health: {sender.Player.Stats.CurrHealth}; Defense: {sender.Player.Stats.Defense}"); return; } int roomId = CommandUtils.GetCurrentRoomId(sender, Map); Item item = Map.Rooms[roomId].Items.FirstOrDefault(t => CommandUtils.FuzzyEquals(t.Actual.Name, e))?.Actual ?? sender.Inventory.Items.FirstOrDefault(t => CommandUtils.FuzzyEquals(t.Name, e)); if (item == null) { // If it's not a item, try and see if the target is an npc HandleNPCExamine(sender, e); return; } if (!item.Commands.Contains("examine")) { sender.Connection.SendMessage("You cannot examine that."); return; } sender.Connection.SendMessage($"You examine the {e}."); sender.Connection.SendMessage($"{item.Description}"); }
void HandleNPCExamine(User sender, string e) { int roomId = CommandUtils.GetCurrentRoomId(sender, Map); NPC npc = Map.Rooms[roomId].NPCs.FirstOrDefault(t => CommandUtils.FuzzyEquals(t.Actual.Name, e))?.Actual; if (npc == null) { // If it's not an npc or a item, try and see if the target is a container HandleContainerExamine(sender, e); return; } if (!npc.Commands.Contains("examine")) { sender.Connection.SendMessage("You cannot examine that."); return; } sender.Connection.SendMessage($"You examine the {e}."); sender.Connection.SendMessage($"{npc.Description}"); }
/* HandleTake and HandleDrop are relatively similar functions that just perform the inverses of each other * HandleTake checks if the item a user wants to take exists in the context of the room they are in. * if item exists, remove it from the room's list of references and add it to the player's inventory list instead */ void HandleTake(User sender, string e) { if (sender.Player.IsDead) { sender.Connection.SendMessage("You cannot do that while defeated!"); return; } int roomId = CommandUtils.GetCurrentRoomId(sender, Map); var target = Map.Rooms[roomId].Items.FirstOrDefault(t => CommandUtils.FuzzyEquals(t.Actual.Name, e)); if (target == null) { sender.Connection.SendMessage("No such object exists."); return; } if (!target.Actual.Commands.Contains("take")) { sender.Connection.SendMessage("You cannot take that."); return; } // Prevent the chance that two users try to take the same item at the same time. lock (Map.Rooms[roomId].Items) { if (Map.Rooms[roomId].Items.Remove(target)) { sender.Inventory.setCurrentRaisedCapacity(target.Actual.Weight); if (sender.Inventory.CurrentCapacity <= sender.Inventory.CarryCapacity) { sender.Inventory.AddToInventory(target.Actual); sender.Connection.SendMessage($"You add the {e} to your inventory."); return; } sender.Connection.SendMessage("You're carrying too much to take that."); } else { sender.Connection.SendMessage("That item is no longer there."); } } }
void HandleHoldDrop(User sender, string e) { int roomID = CommandUtils.GetCurrentRoomId(sender, Map); var target = sender.Player.Held.FirstOrDefault(t => CommandUtils.FuzzyEquals(t.Name, e)); if (target == null) { sender.Connection.SendMessage("You are not holding that."); return; } if (!target.Commands.Contains("drop")) { sender.Connection.SendMessage("You cannot drop that."); return; } sender.Player.Drop(target); sender.Inventory.setCurrentRaisedCapacity(target.Weight); CommandUtils.RemoveItemChangeStats(target, sender); sender.Inventory.AddToInventory(target); }
// Look gets the description of a room. public void HandleLookEvent(object sender, EventArgs e) { User s = sender as User; int index = CommandUtils.GetCurrentRoomId(s, Map); s.Connection.SendMessage($"You look around:\n{Map.Rooms[index].Description}"); if (CommandUtils.HasItems(s, Map)) { s.Connection.SendMessage($"You see some interesting things: {string.Join(", ", Map.Rooms[index].Items.Select(t => t.Actual))}."); } if (CommandUtils.HasContainers(s, Map)) { s.Connection.SendMessage($"You see some containers that might contain useful things: {string.Join(", ", Map.Rooms[index].Containers.Select(t => t.Actual))}."); } if (CommandUtils.HasDoors(s, Map)) { s.Connection.SendMessage($"You see doors to: {string.Join(", ", Map.Rooms[index].Doors.Select(t => t.Actual))}."); } if (Map.Rooms[index].DeadNPCs.ToList().Count > 0) { s.Connection.SendMessage($"There are some dead bodies here: {string.Join(", ", Map.Rooms[index].DeadNPCs.Select(t => t.Actual.Name))}"); } }
void HandleOpen(User sender, string e) { if (sender.Player.IsDead) { sender.Connection.SendMessage("You cannot do that while defeated!"); return; } int roomId = CommandUtils.GetCurrentRoomId(sender, Map); var target = Map.Rooms[roomId].Containers.FirstOrDefault(t => CommandUtils.FuzzyEquals(t.Actual.Name, e)); if (target == null) { sender.Connection.SendMessage("No such container exists."); return; } if (!target.Actual.IsUnlocked) { sender.Connection.SendMessage("This container is locked."); return; } lock (Map.Rooms[roomId].Containers) { sender.Connection.SendMessage($"You open the {target.Actual.Name}."); if (target.Actual.Contents.Count != 0) { sender.Connection.SendMessage($"The {target.Actual.Name} contains some items!"); } else { sender.Connection.SendMessage($"The {target.Actual.Name} is empty."); } target.Actual.UseContainer(sender); } }
// Talk to an NPC void HandleTalkTo(User sender, string e) { if (sender.Player.IsDead) { sender.Connection.SendMessage("You cannot do that while defeated!"); return; } int currRoom = CommandUtils.GetCurrentRoomId(sender, Map); NPC target = CommandUtils.GetTarget(currRoom, e, Map); if (target == null) { sender.Connection.SendMessage("You babble to no one in particular for a moment."); return; } if (CommandUtils.FuzzyEquals(target.Faction, "enemy")) { sender.Connection.SendMessage("While talking your way out of confrontation is admirable, it won't work in this situation."); HandleAttack(sender, e); return; } if (CommandUtils.FuzzyEquals(target.Faction, "dead")) { sender.Connection.SendMessage("He's dead, Jim."); return; } target.Conversation = new Conversation(target, sender); sender.Player.Conversation = target.Conversation; target.Conversation.Greeting(); while (target.Conversation != null && sender.Player.Conversation != null) { sender.Connection.SendMessage(@"w: Who n: News t: Trade q: Quest b: Bye"); string action = sender.Connection.ReadMessage(); if (CommandUtils.FuzzyEquals(action, "w")) { target.Conversation.Who(); } if (CommandUtils.FuzzyEquals(action, "n")) { target.Conversation.News(); sender.Connection.SendMessage("News placeholder"); } if (CommandUtils.FuzzyEquals(action, "t")) { if (CommandUtils.FuzzyEquals(target.Faction, "ally") || CommandUtils.FuzzyEquals(target.Faction, "neutral")) { target.Conversation.Trade(); } else { sender.Connection.SendMessage(target.Conversation.TradeFlavor); } } if (CommandUtils.FuzzyEquals(action, "q")) { if (CommandUtils.FuzzyEquals(target.Faction, "ally") || (CommandUtils.FuzzyEquals(target.Faction, "neutral"))) { if (target.HasQuest) { target.Conversation.Quest(); } else { sender.Connection.SendMessage($"{target.Name} does not have a quest for you."); } } else { sender.Connection.SendMessage(target.Conversation.QuestFlavor); } } if (CommandUtils.FuzzyEquals(action, "b")) { target.Conversation.Bye(); break; } } target.Conversation = null; sender.Player.Conversation = null; }
// Attack an enemy void HandleAttack(User sender, string e) { if (sender.Player.IsDead) { sender.Connection.SendMessage("You cannot do that while defeated!"); return; } int currRoom = CommandUtils.GetCurrentRoomId(sender, Map); NPC target = CommandUtils.GetTarget(currRoom, e, Map); // Make sure the target is actually attackable if (target == null) { sender.Connection.SendMessage("You cannot attack that."); return; } if (CommandUtils.FuzzyEquals(target.Faction, "ally")) { sender.Connection.SendMessage("You cannot attack friendly people!"); return; } if (CommandUtils.FuzzyEquals(target.Faction, "dead")) { sender.Connection.SendMessage("You cannot attack dead bodies!"); return; } // If these checks pass, then there is an available target to fight // Check and see if the target is already engaged : if so, join the target session // RoomSay($"{sender.Name} is attacking the {target.Name}!", sender); if (target.Combat == null) { target.Combat = new Combat(target); } target.Combat.Combatants.Add(sender); sender.Player.Combat = target.Combat; // Pre-emptively get the direction to run in in case the user decides to try to run. var runDir = Map.Rooms[CommandUtils.GetCurrentRoomId(sender, Map)].Doors.Where(d => !d.Actual.Locked).FirstOrDefault()?.Actual; // Combat loop: check turns while (target.Combat != null && sender.Player.Combat != null) { sender.Player.IsBlocking = false; sender.Connection.SendMessage(@"a: Attack d: Defend h: Heal r: Run"); if (sender.Player.Stats.CurrHealth <= 0) { break; } else { string action = sender.Connection.ReadMessage(); if (CommandUtils.FuzzyEquals(action, "a")) { target.Combat.Attack(sender); } if (CommandUtils.FuzzyEquals(action, "d")) { target.Combat.Defend(sender); } if (CommandUtils.FuzzyEquals(action, "h")) { sender.Connection.SendMessage("Consume what?"); var consumables = sender.Inventory.Items.Where(t => t.IsConsumable); foreach (Item item in consumables) { sender.Connection.SendMessage(item.Name); } string choice = sender.Connection.ReadMessage(); HandleEat(sender, choice); } if (CommandUtils.FuzzyEquals(action, "r")) { target.Combat.Run(sender, runDir); target.Combat = null; break; } } if (target.Health <= 0) { break; } target.Combat.EnemyTurn(); } if (sender.Player.Stats.CurrHealth <= 0) { sender.Player.Combat = null; target.Combat = null; sender.Connection.SendMessage("You have been defeated!"); if (Users.Count > 2) { sender.Connection.SendMessage("Would you like to wait for a revive? (y/n)"); string action = sender.Connection.ReadMessage(); if (CommandUtils.FuzzyEquals(action, "y")) { sender.Player.IsDead = true; return; } } sender.Connection.SendMessage("As you were the only soul in this place, you have been sent back to the start."); foreach (Item items in sender.Inventory.Items.ToList()) { sender.Inventory.RemoveFromInventory(items); XMLReference <Item> item = new XMLReference <Item> { Actual = items }; Map.Rooms[CommandUtils.GetCurrentRoomId(sender, Map)].Items.Add(item); } sender.Player.Stats.CurrHealth = sender.Player.Stats.MaxHealth; sender.CurrRoomId = 0001; return; } // After this loop, the target is dead. Remove them from the npc list and add them to the dead list/faction. target.Faction = "dead"; // Upon death, an npc's inventory gets dropped to the room. /* foreach(Item items in target.Inventory.Items.ToList()) * { * target.Inventory.RemoveFromInventory(items); * XMLReference<Item> item = new XMLReference<Item> { Actual = items }; * Map.Rooms[CommandUtils.GetCurrentRoomId(sender, Map)].Items.Add(item); * } */ foreach (var i in Map.Rooms[CommandUtils.GetCurrentRoomId(sender, Map)].NPCs.ToList()) { if (i.Actual.Name == target.Name) { Map.Rooms[CommandUtils.GetCurrentRoomId(sender, Map)].NPCs.Remove(i); Map.Rooms[CommandUtils.GetCurrentRoomId(sender, Map)].DeadNPCs.Add(i); } } sender.Connection.SendMessage("Send 'q' to exit combat."); sender.Player.Combat = null; target.Combat = null; }
/* HandleGo handles moving between rooms. * TODO: Find a better way to handle the RoomsIConnect list - currently, in the XML, rooms must be * placed in the order of CURRENT ROOM in index 0 and CONNECTING ROOM in index 1 * there's probably a better way to handle this situation. */ void HandleGo(User sender, string e) { if (sender.Player.IsDead) { sender.Connection.SendMessage("You cannot do that while defeated!"); return; } if (CommandUtils.FuzzyEquals(e, "north")) { e = "n"; } if (CommandUtils.FuzzyEquals(e, "south")) { e = "s"; } if (CommandUtils.FuzzyEquals(e, "east")) { e = "e"; } if (CommandUtils.FuzzyEquals(e, "west")) { e = "w"; } int currentRoomId = CommandUtils.GetCurrentRoomId(sender, Map); int numDoors = Map.Rooms[currentRoomId].Doors.Select(t => t.Actual).Count(); var directionGone = Map.Rooms[currentRoomId].Doors.FirstOrDefault(t => CommandUtils.FuzzyEquals(t.Actual.Direction, e))?.Actual; if (numDoors == 0) { sender.Connection.SendMessage("There are no doors here. You cannot go anywhere."); return; } if (directionGone == null) { sender.Connection.SendMessage("There is no door there."); return; } void proceed() { sender.CurrRoomId = directionGone.RoomsIConnect[1]; } if (!directionGone.Locked) { proceed(); return; } if (sender.Player.Stats.Dexterity >= directionGone.minDexterity) { sender.Connection.SendMessage("Although the door is locked, you are deft enough to pick your way in."); proceed(); directionGone.Locked = false; return; } if (directionGone.HasKey) { if (CommandUtils.OwnsItem(sender, "key")) { proceed(); return; } sender.Connection.SendMessage("This door is locked and has a key. Look around!"); } else { sender.Connection.SendMessage("You are unable to open the door."); } }
// Who gets a list of players currently in the sender's room. public void HandleWhoEvent(object sender, EventArgs e) { User s = sender as User; List <User> currentUsers = new List <User>(); lock (Users) { foreach (User user in Users) { if (CommandUtils.GetCurrentRoomId(user, Map) == CommandUtils.GetCurrentRoomId(s, Map)) { currentUsers.Add(user); } } currentUsers.Remove(s); } // if there is one player if (currentUsers.Count == 1) { s.Connection.SendMessage($"You see your ally, {string.Join(", ", currentUsers.Select(t => t.Name))}."); } // if there are multiple players else if (currentUsers.Count > 1) { s.Connection.SendMessage($"You see your allies, {string.Join(", ", currentUsers.Select(t => t.Name))}."); } // if there are no other players else { s.Connection.SendMessage("You have no allies nearby."); } if (CommandUtils.HasNPCs(s, Map)) { List <NPC> friendlies = new List <NPC>(); List <NPC> meanies = new List <NPC>(); List <NPC> sneakies = new List <NPC>(); List <NPC> detectedSneakies = new List <NPC>(); foreach (var i in Map.Rooms[CommandUtils.GetCurrentRoomId(s, Map)].NPCs) { // each i is a reference to an entity if (CommandUtils.FuzzyEquals(i.Actual.Faction, "enemy")) { if (i.Actual.IsHidden) { sneakies.Add(i.Actual); } else { meanies.Add(i.Actual); } } else { friendlies.Add(i.Actual); } } if (friendlies.Count > 0) { s.Connection.SendMessage($"You can see: {string.Join(", ", friendlies.Select(t => t.Name))}"); } if (meanies.Count > 0) { s.Connection.SendMessage($"You can see some enemies: {string.Join(", ", meanies.Select(t => t.Name))}"); } if (sneakies.Count > 0) { // sender.Player.Stats.Dexterity >= directionGone.Actual.minDexterity foreach (NPC entity in sneakies) { if (s.Player.Stats.Perception >= entity.minPerception) { detectedSneakies.Add(entity); } } if (detectedSneakies.Count > 0) { s.Connection.SendMessage($"Although they are trying to be stealthy, you can see some enemies lurking in the shadows: {string.Join(", ", detectedSneakies.Select(t => t.Name))}"); return; } s.Connection.SendMessage("You don't see anyone new, but you sense a strange presence."); return; } } }