public bool HandleClick(int x, int y, out DRObjects.Enums.InternalActionEnum? instruction, out object[] args) { //We always handle a click by sending the instruction instruction = this.action; args = this.args; return true; }
public bool HandleKeyboard(Microsoft.Xna.Framework.Input.KeyboardState keyboard, out DRObjects.Enums.ActionType? actionType, out object[] args, out DRObjects.MapCoordinate coord, out bool destroy) { //we don't handle the keyboard actionType = null; args = null; coord = null; destroy = false; return false; }
bool IGameInterfaceComponent.HandleClick(int x, int y, MouseActionEnum mouse, out DRObjects.Enums.ActionType? actionType,out InternalActionEnum? internalActionType, out object[] args, out MapItem itm, out DRObjects.MapCoordinate coord, out bool destroy) { //This component will 'absorb' the click, but do nothing whatsoever. actionType = null; args = null; coord = null; destroy = false; internalActionType = null; itm = null; return true; }
public bool HandleClick(int x, int y, Objects.Enums.MouseActionEnum mouseAction, out DRObjects.Enums.ActionType? actionType, out InternalActionEnum? internalActionType, out object[] args, out MapItem item, out DRObjects.MapCoordinate coord, out bool destroy) { //This does nothing item = null; args = null; coord = null; destroy = false; actionType = null; internalActionType = null; return visible; //If it's visible - block it. Otherwise do nothing }
public bool HandleClick(int x, int y, Objects.Enums.MouseActionEnum mouseAction, out DRObjects.Enums.ActionType? actionType,out InternalActionEnum? internalActionType, out object[] args,out MapItem itm, out DRObjects.MapCoordinate coord, out bool destroy) { if (!visible) { itm = null; actionType = null; destroy = false; coord = null; args = null; internalActionType = null; return false; } //Check if we're in the middle of an animation cycle if (this.bigSizeSwitch == 0 || this.bigSizeSwitch == BIGSIZE) { //toggle big mode this.bigMode = !this.bigMode; if (this.bigMode) { //Expand rectangle by 200 pixels - gradually this.bigSizeSwitch = 0; // this.rect.Y -= 200; // this.rect.Height += 200; } else { this.bigSizeSwitch = 200; // this.rect.Y += 200; // this.rect.Height -= 200; } } actionType = null; destroy = false; coord = null; args = null; internalActionType = null; itm = null; return true; }
public bool HandleKeyboard(KeyboardState keyboard, out DRObjects.Enums.ActionType? actionType, out object[] args, out DRObjects.MapCoordinate coord, out bool destroy) { actionType = null; args = null; coord = null; destroy = false; //If the user moves, destroy it if (keyboard.GetPressedKeys().Contains(Keys.Left) || keyboard.GetPressedKeys().Contains(Keys.Right) || keyboard.GetPressedKeys().Contains(Keys.Down) || keyboard.GetPressedKeys().Contains(Keys.Up)) { destroy = true; } return false; }
/// <summary> /// Performs the action and handles feedback /// </summary> /// <param name="?"></param> public void PerformAction(MapCoordinate coord, MapItem item, DRObjects.Enums.ActionType actionType, object[] args) { //remove any viewtiletext components or contextmenu components for (int i = 0; i < interfaceComponents.Count; i++) { var type = interfaceComponents[i].GetType(); if (type.Equals(typeof(ViewTileTextComponent)) || type.Equals(typeof(ContextMenuComponent))) { //delete interfaceComponents.RemoveAt(i); i--; } } ActionFeedback[] fb = UserInterfaceManager.PerformAction(coord, item, actionType, args); //go through all the feedback for (int i = 0; i < fb.Length; i++) { ActionFeedback feedback = fb[i]; if (feedback == null) { continue; } if (feedback.GetType().Equals(typeof(AttackFeedback))) { AttackFeedback af = feedback as AttackFeedback; var combatAf = CombatManager.Attack(af.Attacker, af.Defender, AttackLocation.CHEST); //always attack the chest var tempFBList = fb.ToList(); tempFBList.AddRange(combatAf); fb = tempFBList.ToArray(); } else if (feedback.GetType().Equals(typeof(OpenInterfaceFeedback))) { OpenInterfaceFeedback oif= feedback as OpenInterfaceFeedback; //Generate one if (oif.Interface.GetType() == typeof(CombatManualInterface)) { var cmi = oif.Interface as CombatManualInterface; CombatManualComponent cmc = new CombatManualComponent(GraphicsDevice.Viewport.Width / 2 - 200, GraphicsDevice.Viewport.Height / 2 - 150, cmi.Manual); interfaceComponents.Add(cmc); } else if (oif.Interface.GetType() == typeof(ThrowItemInterface)) { var tii = oif.Interface as ThrowItemInterface; //Do we have LoS to that point? if (GameState.LocalMap.HasDirectPath(GameState.PlayerCharacter.MapCharacter.Coordinate,tii.Coordinate)) { ThrowItemComponent tic = new ThrowItemComponent(Mouse.GetState().X, Mouse.GetState().Y, tii.Coordinate, GameState.PlayerCharacter); interfaceComponents.Add(tic); } else { var tempFBList = fb.ToList(); tempFBList.Add(new TextFeedback("You can't see there")); fb = tempFBList.ToArray(); } } } else if (feedback.GetType().Equals(typeof(TextFeedback))) { MouseState mouse = Mouse.GetState(); //Display it interfaceComponents.Add(new ViewTileTextComponent(mouse.X + 15, mouse.Y, (feedback as TextFeedback).Text)); } else if (feedback.GetType().Equals(typeof(LogFeedback))) { GameState.NewLog.Add(feedback as LogFeedback); } else if (feedback.GetType().Equals(typeof(InterfaceToggleFeedback))) { InterfaceToggleFeedback iop = feedback as InterfaceToggleFeedback; if (iop.InterfaceComponent == InternalActionEnum.OPEN_ATTACK && iop.Open) { //Open the attack interface for a particular actor. If one is not open already //Identify the actor in question var actorMapItem = iop.Argument as LocalCharacter; //Locate the actual actor Actor actor = GameState.LocalMap.Actors.Where(lm => lm.MapCharacter == actorMapItem).FirstOrDefault(); //Yep, it's a pointer equals bool openAlready = false; //Do we have one open already? foreach (AttackActorComponent aac in interfaceComponents.Where(ic => ic.GetType().Equals(typeof(AttackActorComponent)))) { if (aac.TargetActor.Equals(actor)) { openAlready = true; break; } } if (!openAlready) { //Open it. Otherwise don't do anything interfaceComponents.Add(new AttackActorComponent(150, 150, GameState.PlayerCharacter, actor) { Visible = true }); } } else if (iop.InterfaceComponent == InternalActionEnum.OPEN_ATTACK && !iop.Open) { //Close it var actor = iop.Argument as Actor; AttackActorComponent component = null; foreach (AttackActorComponent aac in interfaceComponents.Where(ic => ic.GetType().Equals(typeof(AttackActorComponent)))) { if (aac.TargetActor.Equals(actor)) { component = aac; } } //Did we have a match? if (component != null) { //remove it interfaceComponents.Remove(component); } } else if (iop.InterfaceComponent == InternalActionEnum.OPEN_TRADE && iop.Open) { //Open trade var arguments = iop.Argument as object[]; TradeDisplayComponent tdc = new TradeDisplayComponent(100, 100, arguments[1] as Actor, arguments[0] as Actor); interfaceComponents.Add(tdc); } else if (iop.InterfaceComponent == InternalActionEnum.OPEN_LOOT) { //Open Loot TreasureChest lootContainer = (iop.Argument as object[])[0] as TreasureChest; LootComponent lc = new LootComponent(100, 100, lootContainer); interfaceComponents.Add(lc); } } else if (feedback.GetType().Equals(typeof(CreateEventFeedback))) { CreateEventFeedback eventFeedback = feedback as CreateEventFeedback; var gameEvent = EventHandlingManager.CreateEvent(eventFeedback.EventName); //Create the actual control interfaceComponents.Add(new DecisionPopupComponent(PlayableWidth / 2 - 150, PlayableHeight / 2 - 150, gameEvent)); } else if (feedback.GetType().Equals(typeof(ReceiveEffectFeedback))) { ReceiveEffectFeedback recFeed = feedback as ReceiveEffectFeedback; EffectsManager.PerformEffect(recFeed.Effect.Actor, recFeed.Effect); } else if (feedback.GetType().Equals(typeof(ReceiveBlessingFeedback))) { ReceiveBlessingFeedback blessFeedback = feedback as ReceiveBlessingFeedback; LogFeedback lg = null; //Bless him! //Later we're going to want to do this properly so other characters can get blessed too BlessingManager.GetAndApplyBlessing(GameState.PlayerCharacter, out lg); if (lg != null) { //Log it GameState.NewLog.Add(lg); } } else if (feedback.GetType().Equals(typeof(ReceiveItemFeedback))) { ReceiveItemFeedback receiveFeedback = feedback as ReceiveItemFeedback; //Determine which item we're going to generate InventoryItemManager iim = new InventoryItemManager(); InventoryItem itm = iim.GetBestCanAfford(receiveFeedback.Category.ToString(), receiveFeedback.MaxValue); if (itm != null) { itm.InInventory = true; GameState.PlayerCharacter.Inventory.Inventory.Add(itm.Category, itm); GameState.NewLog.Add(new LogFeedback(InterfaceSpriteName.SUN, Color.DarkGreen, "You throw in your offering. You then see something glimmer and take it out")); } else { GameState.NewLog.Add(new LogFeedback(InterfaceSpriteName.MOON, Color.DarkBlue, "You throw in your offering. Nothing appears to be there. Hmm...")); } } else if (feedback.GetType().Equals(typeof(LocationChangeFeedback))) { //Remove settlement button and interface var locDetails = this.interfaceComponents.Where(ic => ic.GetType().Equals(typeof(LocationDetailsComponent))).FirstOrDefault(); if (locDetails != null) { this.interfaceComponents.Remove(locDetails); } var button = this.menuButtons.Where(mb => (mb as AutoSizeGameButton).Action == InternalActionEnum.TOGGLE_SETTLEMENT).FirstOrDefault(); if (button != null) { this.menuButtons.Remove(button); } LocationChangeFeedback lce = feedback as LocationChangeFeedback; if (lce.Location != null) { LoadLocation(lce.Location); if (lce.Location is Settlement) { //Makde the components visible LocationDetailsComponent ldc = new LocationDetailsComponent(GameState.LocalMap.Location as Settlement, PlayableWidth - 170, 0); ldc.Visible = true; interfaceComponents.Add(ldc); menuButtons.Add(new AutoSizeGameButton(" Settlement ", this.game.Content, InternalActionEnum.TOGGLE_SETTLEMENT, new object[] { }, 270, GraphicsDevice.Viewport.Height - 35)); Window_ClientSizeChanged(null, null); //button is in the wrong position for some reason } GameState.LocalMap.IsGlobalMap = false; } else if (lce.VisitMainMap) { //If it's a bandit camp or a site, update the values of the members if (GameState.LocalMap.Location as MapSite != null || GameState.LocalMap.Location as BanditCamp != null) { if (GameState.LocalMap.Location as BanditCamp != null) { var banditCamp = GameState.LocalMap.Location as BanditCamp; banditCamp.BanditTotal = GameState.LocalMap.Actors.Count(a => a.IsActive && a.IsAlive && !a.IsPlayerCharacter && a.EnemyData != null && a.EnemyData.Profession == ActorProfession.WARRIOR); //Has it been cleared? if (banditCamp.BanditTotal == 0) { //Find the item var campItem = GameState.GlobalMap.CampItems.FirstOrDefault(ci => ci.Camp == (GameState.LocalMap.Location as BanditCamp)); if (campItem != null) { campItem.IsActive = false; GameState.GlobalMap.CampItems.Remove(campItem); //Also find the coordinate of the camp, grab a circle around it and remove the owner var mapblocks = GameState.GlobalMap.GetBlocksAroundPoint(campItem.Coordinate, WorldGenerationManager.BANDIT_CLAIMING_RADIUS); foreach (var block in mapblocks) { var tile = (block.Tile as GlobalTile); //Owned by bandit if (tile.Owner == 50) { tile.RemoveOwner(); } } //Yes. Let's clear the camp GameState.NewLog.Add(new LogFeedback(InterfaceSpriteName.SWORD, Color.Black, "You drive the bandits away from the camp")); } } } else if (GameState.LocalMap.Location as MapSite != null) { var site = GameState.LocalMap.Location as MapSite; site.SiteData.ActorCounts.Clear(); foreach (var actorProfession in (ActorProfession[])Enum.GetValues(typeof(ActorProfession))) { int count = GameState.LocalMap.Actors.Count(a => a.IsActive && a.IsAlive && !a.IsPlayerCharacter && a.EnemyData != null && a.EnemyData.Profession == actorProfession); site.SiteData.ActorCounts.Add(actorProfession, count); } if (site.SiteData.ActorCounts[ActorProfession.WARRIOR] == 0) { //Out of warriors, abandon it. We'll decide who really owns it later site.SiteData.OwnerChanged = true; site.SiteData.MapRegenerationRequired = true; site.SiteData.Owners = OwningFactions.ABANDONED; site.SiteData.ActorCounts = new Dictionary<ActorProfession, int>(); } } } //Serialise the old map GameState.LocalMap.SerialiseLocalMap(); //Clear the stored location items GameState.LocalMap.Location = null; LoadGlobalMap(GameState.PlayerCharacter.GlobalCoordinates); GameState.LocalMap.IsGlobalMap = true; } else if (lce.RandomEncounter != null) { //Get the biome LoadRandomEncounter(lce.RandomEncounter.Value); } } else if (feedback.GetType().Equals(typeof(DropItemFeedback))) { DropItemFeedback dif = feedback as DropItemFeedback; //Drop the item underneath the player GameState.LocalMap.GetBlockAtCoordinate(dif.ItemToDrop.Coordinate).PutItemUnderneathOnBlock(dif.ItemToDrop); //Remove from inventory dif.ItemToDrop.InInventory = false; GameState.PlayerCharacter.Inventory.Inventory.Remove(dif.ItemToDrop.Category, dif.ItemToDrop); } else if (feedback.GetType().Equals(typeof(TimePassFeedback))) { TimePassFeedback tpf = feedback as TimePassFeedback; //Move time forth GameState.IncrementGameTime(DRTimeComponent.MINUTE, tpf.TimePassInMinutes); //Is the character dead? if (!GameState.PlayerCharacter.IsAlive) { var gameEvent = EventHandlingManager.CreateEvent("Hunger Death"); //Create the actual control interfaceComponents.Add(new DecisionPopupComponent(PlayableWidth / 2 - 150, PlayableHeight / 2 - 150, gameEvent)); } } else if (feedback.GetType().Equals(typeof(VisitedBlockFeedback))) { VisitedBlockFeedback vbf = feedback as VisitedBlockFeedback; //Visit a region equal to the line of sight of the player character - var blocks = GameState.LocalMap.GetBlocksAroundPoint(vbf.Coordinate, GameState.PlayerCharacter.LineOfSight); //Only do the ones which can be ray traced foreach (var block in RayTracingHelper.RayTraceForExploration(blocks, GameState.PlayerCharacter.MapCharacter.Coordinate)) { block.WasVisited = true; } } else if (feedback.GetType().Equals(typeof(DescendDungeonFeedback))) { DescendDungeonFeedback ddf = feedback as DescendDungeonFeedback; (GameState.LocalMap.Location as Dungeon).DifficultyLevel++; this.LoadLocation(GameState.LocalMap.Location, true); } } //Update the log control log.UpdateLog(); }
/// <summary> /// Generates enemies on the map. /// </summary> /// <param name="enemyCount"></param> /// <param name="enemyType"></param> /// <returns></returns> public MapBlock[,] GenerateEnemies(MapBlock[,] blocks, int enemyCount, string enemyType, out DRObjects.Actor[] actors, int level, int equipmentCost = 0) { ItemFactory.ItemFactory fact = new ItemFactory.ItemFactory(); List<Actor> actorList = new List<Actor>(); //We'll just pick blocks at random until we fail 50 times in a row or run out of enemies to place int failureCount = 0; for (int i = 0; i < enemyCount; i++) { if (failureCount == 50) { break; } int x = random.Next(blocks.GetLength(0)); int y = random.Next(blocks.GetLength(1)); //Is the block free if (blocks[x, y].MayContainItems) { int returnedID = -1; //Put the enemy in there //Get the basic Actor object double multiplier = GameState.Random.Next(75, 125); multiplier /= 100; //So we get a number between 0.75 and 1.25 Actor actor = ActorGeneration.CreateActor(enemyType, null, null, (int)(level * multiplier), (int)(equipmentCost * multiplier), null, out returnedID); var mapObject = fact.CreateItem("enemies", returnedID); (mapObject as LocalCharacter).Actor = actor; //Create the Actor actor.GlobalCoordinates = null; //useless for now actor.IsPlayerCharacter = false; actor.MapCharacter = mapObject; actorList.Add(actor); blocks[x, y].ForcePutItemOnBlock(mapObject); int missionType = random.Next(3); if (missionType == 0) { //33% of them will Wander - WanderMission mission = new WanderMission(); mission.WanderPoint = new MapCoordinate(x, y, 0, MapType.LOCAL); mission.WanderRectangle = new Rectangle(0, 0, blocks.GetLength(0), blocks.GetLength(1)); actor.MissionStack.Push(mission); } else if (missionType == 1) { //33% will idle IdleMission mission = new IdleMission(); actor.MissionStack.Push(mission); } else { //The rest will patrol PatrolMission mission = new PatrolMission(); //Don't give them the point. We;ll choose it later actor.MissionStack.Push(mission); } failureCount = 0;//reset } else { failureCount++; i--; //And again } } //return the map actors = actorList.ToArray(); return blocks; }
public bool HandleKeyboard(Microsoft.Xna.Framework.Input.KeyboardState keyboard, out DRObjects.Enums.ActionType? actionType, out object[] args, out DRObjects.MapCoordinate coord, out bool destroy) { actionType = null; args = null; coord = null; destroy = false; if (keyboard.GetPressedKeys().Length > 0) { //Destroy it destroy = true; } return true; }
public bool HandleKeyboard(Microsoft.Xna.Framework.Input.KeyboardState keyboard, out DRObjects.Enums.ActionType? actionType, out object[] args, out DRObjects.MapCoordinate coord, out bool destroy) { //This does nothing args = null; coord = null; destroy = false; actionType = null; return false; //This never does anything }
public bool HandleClick(int x, int y, Objects.Enums.MouseActionEnum mouseAction, out DRObjects.Enums.ActionType? actionType, out DRObjects.Enums.InternalActionEnum? internalActionType, out object[] args, out MapItem itm, out DRObjects.MapCoordinate coord, out bool destroy) { actionType = null; internalActionType = null; args = null; coord = null; destroy = false; itm = null; feedbackText = String.Empty; feedbackColour = Color.White; //Clicked on the button? if (swapButton.Contains(x, y)) { Buy = !Buy; //Remove all selections foreach (var item in row1Items.Union(row2Items).Union(row3Items)) { item.Selected = false; } return true; } if (closeButton.Contains(x, y)) { //Close it destroy = true; return true; } if (confirmButton.Contains(x, y)) { //Are they next to each other? if (this.VendorActor.MapCharacter.Coordinate - this.PlayerActor.MapCharacter.Coordinate > 2) { feedbackText = "You're too far away"; feedbackColour = Color.DarkRed; return true; //invalid } //Valid ? if (this.Buy) { if (this.totalSelected > PlayerActor.Inventory.TotalMoney) { feedbackText = "You can't afford that"; feedbackColour = Color.DarkRed; //Nope return true; } //Allright, lets do this //Take the items foreach (var item in GetSelected()) { this.VendorActor.VendorDetails.Stock.Remove(item.Item.Category, item.Item); this.PlayerActor.Inventory.Inventory.Add(item.Item.Category, item.Item); } //Give him the money this.PlayerActor.Inventory.TotalMoney -= totalSelected; this.VendorActor.VendorDetails.Money += totalSelected; //Remove all selections foreach (var item in row1Items.Union(row2Items).Union(row3Items)) { item.Selected = false; } feedbackText = "You finalise your purchase"; feedbackColour = Color.DarkGreen; } else { if (this.totalSelected > this.VendorActor.VendorDetails.Money) { //Nope feedbackText = "The Vendor hasn't got enough money to pay for those"; feedbackColour = Color.DarkRed; return true; } //Allright, lets do this //Take the items foreach (var item in GetSelected()) { this.PlayerActor.Inventory.Inventory.Remove(item.Item.Category, item.Item); this.VendorActor.VendorDetails.Stock.Add(item.Item.Category, item.Item); } //Give him the money this.PlayerActor.Inventory.TotalMoney += totalSelected; this.VendorActor.VendorDetails.Money -= totalSelected; //Remove all selections foreach (var item in row1Items.Union(row2Items).Union(row3Items)) { item.Selected = false; } feedbackText = "You finalise your trade"; feedbackColour = Color.DarkGreen; } } for (int i = 0; i < categories.Count; i++) { if (categories[i].Contains(x, y)) { //Change category! this.ChosenCategory = i; //Remove all selections foreach (var item in row1Items.Union(row2Items).Union(row3Items)) { item.Selected = false; } //Handled. Naught else return true; } } //Have we clicked on an item ? List<InventoryItemRectangle> allItemBoxes = new List<InventoryItemRectangle>(); allItemBoxes.AddRange(row1Items); allItemBoxes.AddRange(row2Items); allItemBoxes.AddRange(row3Items); foreach (InventoryItemRectangle rect in allItemBoxes) { if (rect.Rect.Contains(x, y)) { //Does it contain an item? if (rect.Item != null) { //Toggle the selection rect.Selected = !rect.Selected; } else { return true; //Empty box } } } return true; }
public bool HandleClick(int x, int y, Objects.Enums.MouseActionEnum mouseAction, out DRObjects.Enums.ActionType? actionType, out DRObjects.Enums.InternalActionEnum? internalActionType, out object[] args, out DRObjects.MapItem item, out DRObjects.MapCoordinate coord, out bool destroy) { actionType = null; internalActionType = null; args = null; item = null; coord = null; destroy = false; //Did they click on one of the Special Attacks ? for(int i=0; i < slotRectangles.Length; i++) { Rectangle sRect = slotRectangles[i]; if (sRect.Contains(x,y)) { this.clickedNumber = i; break; } } //Did they click on cancel? if (this.cancelRect.Contains(x,y)) { destroy = true; return true; } //Did they click on learn? if (this.learnRect.Contains(x,y)) { if (this.newAttack.SkillLevelRequired <= GameState.PlayerCharacter.Attributes.GetSkill(SkillName.FIGHTER)) { //Learn it! Woo! GameState.PlayerCharacter.SpecialAttacks[this.clickedNumber.Value] = this.newAttack; //Destroy the inventory item this.cm.IsActive = false; this.cm.InInventory = false; GameState.PlayerCharacter.Inventory.Inventory.Remove(this.cm.Category, this.cm); destroy = true; return true; } else { //Can't learn it } } return true; }
/// <summary> /// Generates a camp /// </summary> /// <returns></returns> public static MapBlock[,] GenerateCamp(int enemies, out MapCoordinate startPoint, out DRObjects.Actor[] enemyArray) { MapBlock[,] map = new MapBlock[MAP_EDGE, MAP_EDGE]; Random random = new Random(); ItemFactory.ItemFactory factory = new ItemFactory.ItemFactory(); int grassTileID = 0; factory.CreateItem(Archetype.TILES, "grass", out grassTileID); //Create a new map which is edge X edge in dimensions and made of grass for (int x = 0; x < MAP_EDGE; x++) { for (int y = 0; y < MAP_EDGE; y++) { MapBlock block = new MapBlock(); map[x, y] = block; block.Tile = factory.CreateItem("tile", grassTileID); block.Tile.Coordinate = new MapCoordinate(x, y, 0, MapType.LOCAL); } } //Now created a wall int pallisadeID = 0; factory.CreateItem(Archetype.MUNDANEITEMS, "pallisade wall lr", out pallisadeID); //Create a square of pallisade wall int startCoord = (MAP_EDGE - FORTIFICATION_EDGE) / 2; int endCoord = MAP_EDGE - ((MAP_EDGE - FORTIFICATION_EDGE) / 2); for (int x = startCoord + 1; x < endCoord; x++) { MapBlock block = map[x, startCoord]; MapItem item = factory.CreateItem("mundaneitems", pallisadeID); block.ForcePutItemOnBlock(item); block = map[x, endCoord]; item = factory.CreateItem("mundaneitems", pallisadeID); block.ForcePutItemOnBlock(item); } pallisadeID = 0; for (int y = startCoord + 1; y < endCoord; y++) { factory.CreateItem(Archetype.MUNDANEITEMS, "pallisade wall tb", out pallisadeID); MapBlock block = map[startCoord, y]; MapItem item = factory.CreateItem("mundaneitems", pallisadeID); block.ForcePutItemOnBlock(item); factory.CreateItem(Archetype.MUNDANEITEMS, "pallisade wall bt", out pallisadeID); block = map[endCoord, y]; item = factory.CreateItem("mundaneitems", pallisadeID); block.ForcePutItemOnBlock(item); } //We need to poke a hole in wall as an entrance //Let's poke one at the top and one at the bottom int center = MAP_EDGE / 2; int rValue = GameState.Random.Next(2); for (int x = -1; x < 2; x++) { if (rValue == 1) { MapBlock block = map[center + x, startCoord]; block.RemoveTopItem(); } else { MapBlock block = map[center + x, endCoord]; block.RemoveTopItem(); } } rValue = GameState.Random.Next(2); for (int y = -1; y < 2; y++) { if (rValue == 1) { MapBlock block = map[startCoord, y + center]; block.RemoveTopItem(); } else { MapBlock block = map[endCoord, y + center]; block.RemoveTopItem(); } } //Now, let's create some maplets in there //There's a single maplet containing the other maplets - let's get it LocalMapXMLParser lm = new LocalMapXMLParser(); Maplet maplet = lm.ParseMapletFromTag("camp"); LocalMapGenerator gen = new LocalMapGenerator(); //TODO: LATER THE OWNER MIGHT NOT BE A BANDIT MapletActorWanderArea[] wanderAreas = null; MapletPatrolPoint[] patrolPoints = null; MapletFootpathNode[] footPath = null; var gennedMap = gen.GenerateMap(grassTileID, null, maplet, false, "", OwningFactions.BANDITS, out enemyArray, out wanderAreas, out patrolPoints,out footPath); gen.JoinMaps(map, gennedMap, startCoord + 1, startCoord + 1); //Let's add some trees and stuff int decorCount = (int)(map.GetLength(1) * 0.50); //Just find as many random points and if it happens to be grass, drop them int itemID = 0; for (int i = 0; i < decorCount; i++) { //Just trees MapItem decorItem = factory.CreateItem(Archetype.MUNDANEITEMS, "tree", out itemID); //Pick a random point MapBlock randomBlock = map[random.Next(map.GetLength(0)), random.Next(map.GetLength(1))]; //Make sure its not inside the camp if (randomBlock.Tile.Coordinate.X >= startCoord && randomBlock.Tile.Coordinate.X <= endCoord && randomBlock.Tile.Coordinate.Y >= startCoord && randomBlock.Tile.Coordinate.Y <= endCoord) { //Not within the camp i--; continue; //try again } if (randomBlock.MayContainItems && randomBlock.Tile.Name == "Grass") { //Yes, can support it randomBlock.ForcePutItemOnBlock(decorItem); } //Otherwise forget all about it } //Now select all the border tiles and put in a "Exit here" border for (int x = 0; x < map.GetLength(0); x++) { MapCoordinate coo = new MapCoordinate(x, 0, 0, MapType.LOCAL); LeaveTownItem lti = new LeaveTownItem(); lti.Coordinate = coo; lti.Description = "path outside the town"; lti.Name = "Leave Town"; lti.Coordinate = coo; map[x, 0].ForcePutItemOnBlock(lti); coo = new MapCoordinate(x, map.GetLength(1) - 1, 0, MapType.LOCAL); lti = new LeaveTownItem(); lti.Coordinate = coo; lti.Description = "path outside the town"; lti.Name = "Leave Town"; lti.Coordinate = coo; map[x, map.GetLength(1) - 1].ForcePutItemOnBlock(lti); } for (int y = 0; y < map.GetLength(1); y++) { MapCoordinate coo = new MapCoordinate(0, y, 0, MapType.LOCAL); LeaveTownItem lti = new LeaveTownItem(); lti.Coordinate = coo; lti.Description = "path outside the town"; lti.Name = "Leave Town"; lti.Coordinate = coo; map[0, y].ForcePutItemOnBlock(lti); coo = new MapCoordinate(map.GetLength(0) - 1, y, 0, MapType.LOCAL); lti = new LeaveTownItem(); lti.Coordinate = coo; lti.Description = "path outside the town"; lti.Name = "Town Borders"; lti.Coordinate = coo; map[map.GetLength(0) - 1, y].ForcePutItemOnBlock(lti); } #region Treasure Room //This is a bit naughty. We need to locate where the tiles become soil MapCoordinate soilStart = null; bool breakOut = false; for (int x = 0; x < map.GetLength(0); x++) { for (int y = 0; y < map.GetLength(1); y++) { if (map[x, y].Tile.Name.ToLower().Equals("soil")) { soilStart = new MapCoordinate(x, y, 0, MapType.LOCAL); breakOut = true; break; } } if (breakOut) { break; } } //Also naughty, we know it's 5x5 #region Inner Wall for (int x = 0; x < 5; x++) { factory.CreateItem(Archetype.MUNDANEITEMS, "pallisade wall lr", out pallisadeID); MapItem item = factory.CreateItem("mundaneitems", pallisadeID); if (x != 2) //hole in the top { map[soilStart.X + x, soilStart.Y].ForcePutItemOnBlock(item); } factory.CreateItem(Archetype.MUNDANEITEMS, "pallisade wall lr", out pallisadeID); item = factory.CreateItem("mundaneitems", pallisadeID); map[soilStart.X + x, soilStart.Y + 5].ForcePutItemOnBlock(item); } for (int y = 0; y < 5; y++) { factory.CreateItem(Archetype.MUNDANEITEMS, "pallisade wall tb", out pallisadeID); MapItem item = factory.CreateItem("mundaneitems", pallisadeID); map[soilStart.X - 1, soilStart.Y + y].ForcePutItemOnBlock(item); factory.CreateItem(Archetype.MUNDANEITEMS, "pallisade wall bt", out pallisadeID); item = factory.CreateItem("mundaneitems", pallisadeID); map[soilStart.X + 5, soilStart.Y + y].ForcePutItemOnBlock(item); } #endregion #endregion #region Patrol Points //Now let's collect the patrol points. We're going to have two possible patrols - one around each of the entrances - and another on the outside corners of the map List<MapCoordinate> outsidePatrol = new List<MapCoordinate>(); outsidePatrol.Add(new MapCoordinate(startCoord - 2, startCoord, 0, MapType.LOCAL)); outsidePatrol.Add(new MapCoordinate(endCoord + 2, startCoord, 0, MapType.LOCAL)); outsidePatrol.Add(new MapCoordinate(endCoord + 2, endCoord, 0, MapType.LOCAL)); outsidePatrol.Add(new MapCoordinate(startCoord - 2, endCoord, 0, MapType.LOCAL)); List<MapCoordinate> insidePatrol = new List<MapCoordinate>(); insidePatrol.Add(new MapCoordinate(center, startCoord + 1, 0, MapType.LOCAL)); insidePatrol.Add(new MapCoordinate(center, endCoord - 1, 0, MapType.LOCAL)); insidePatrol.Add(new MapCoordinate(startCoord + 1, center, 0, MapType.LOCAL)); insidePatrol.Add(new MapCoordinate(endCoord - 1, center, 0, MapType.LOCAL)); //Go through all of those and make sure they're clear of anything that wouldn't let them walk upon them foreach (var coordinate in outsidePatrol) { map[coordinate.X, coordinate.Y].RemoveTopItem(); } foreach (var coordinate in insidePatrol) { map[coordinate.X, coordinate.Y].RemoveTopItem(); } #endregion #region Actors enemyArray = CreateBandits(enemies, outsidePatrol.Select(op => new PatrolPoint() { AcceptableRadius = 2, Coordinate = op }).ToList(), insidePatrol.Select(op => new PatrolPoint() { AcceptableRadius = 2, Coordinate = op }).ToList()); int tries = 0; //Put them on the mappity map for (int i = 0; i < enemyArray.Length; i++) { Actor actor = enemyArray[i]; int randomX = random.Next(map.GetLength(0)); int randomY = random.Next(map.GetLength(1)); if (map[randomX, randomY].MayContainItems) { //Plop it on there actor.MapCharacter.Coordinate = new MapCoordinate(randomX, randomY, 0, MapType.LOCAL); map[randomX, randomY].ForcePutItemOnBlock(actor.MapCharacter); tries = 0; ////If they are wandering, make them wander in the right place //var mission = actor.MissionStack.Peek(); //if (mission.MissionType == ActorMissionType.WANDER) //{ // var wander = mission as WanderMission; // wander.WanderPoint = new MapCoordinate(actor.MapCharacter.Coordinate); // wander.WanderRectangle = new Rectangle(startCoord, startCoord, FORTIFICATION_EDGE, FORTIFICATION_EDGE); //} } else { tries++; i--; } if (tries >= 50) { //give up continue; } } #endregion startPoint = new MapCoordinate(map.GetLength(0) / 2, 0, 0, MapType.LOCAL); return map; }
/// <summary> /// Generates a dungeon having a particular amount of tiers, trap rooms, guard rooms and treasure rooms /// </summary> /// <param name="tiers">How many 'layers' the dungeon contains</param> /// <param name="enemyArray">A list of enemy actors</param> /// <param name="guardRooms">The maximum amount of guardrooms contained in the dungeon</param> /// <param name="maxOwnedPopulation">For each owned room which generates enemies, the maximum amount GENERATED in each room (does not preclude patrols from entering the same room)</param> /// <param name="maxWildPopulation">For each wild room which generates enemies, the maximum amount GENERATED in each room.</param> /// <param name="ownerType">For each owned room, the type of the enemies to create</param> /// <param name="percentageOwned">The percentage of the rooms which are owned as opposed to being wild. Bear in mind that wild rooms can spawn quite a bit of enemies</param> /// <param name="pointsOfInterest">The points of interest (ie guard and treasure rooms for instance) which have been generated. Used for patrols</param> /// <param name="startPoint">The entrance start point</param> /// <param name="utilityRooms">The maximum amount of Utility rooms to generate - these might contain civilian orcs which ignore the maxOwnedPopulation value</param> /// <param name="treasureRooms">The maximum amount of teasure rooms to generate</param> /// <returns></returns> public MapBlock[,] GenerateDungeon(int tiers, int utilityRooms, int guardRooms, int treasureRooms, string ownerType, decimal percentageOwned, int maxWildPopulation, int maxOwnedPopulation, out MapCoordinate startPoint, out DRObjects.Actor[] enemyArray, out List<PointOfInterest> pointsOfInterest) { startPoint = new MapCoordinate(0, 0, 0, MapType.LOCAL); pointsOfInterest = new List<PointOfInterest>(); List<DRObjects.Actor> enemies = new List<DRObjects.Actor>(); List<CitadelRoom> rooms = new List<CitadelRoom>(); int uniqueID = 0; //Start with the root node CitadelRoom root = new CitadelRoom(); root.SquareNumber = (int)Math.Ceiling((double)WIDTH / 2); root.TierNumber = 0; root.UniqueID = uniqueID++; root.Connections.Add(-1); //this is a special id. We'll use it to create a start point rooms.Add(root); int currentTier = 1; int square = (int)Math.Ceiling((double)WIDTH / 2); CitadelRoom focusNode = root; Random random = new Random(DateTime.UtcNow.Millisecond); while (currentTier < tiers) { //Create a new node CitadelRoom newNode = new CitadelRoom(); newNode.SquareNumber = square; newNode.TierNumber = currentTier; newNode.UniqueID = uniqueID++; newNode.CitadelRoomType = CitadelRoomType.EMPTY_ROOM; //connect the focus node to this node focusNode.Connections.Add(newNode.UniqueID); newNode.Connections.Add(focusNode.UniqueID); //change the focus node focusNode = newNode; //aaaand add it to the list rooms.Add(newNode); //Now we decide whether to stay in the same tier - or increase the tier int randomNumber = random.Next(100); int siblings = rooms.Where(r => r.TierNumber.Equals(currentTier)).Count(); int treshold = 0; switch (siblings) { case 1: treshold = PROB_2; break; case 2: treshold = PROB_3; break; case 3: treshold = PROB_4; break; case 4: treshold = PROB_5; break; default: treshold = 0; break; //NEVER } if (randomNumber < treshold) { //then stay in the same place - go either left or right. Can we go in that direction? bool canGoRight = !rooms.Any(r => (r.SquareNumber.Equals(square + 1) && r.TierNumber.Equals(currentTier)) || square + 1 > WIDTH); bool canGoLeft = !rooms.Any(r => (r.SquareNumber.Equals(square - 1) && r.TierNumber.Equals(currentTier)) || square - 1 < 0); if (canGoLeft && canGoRight) { //pick one at random square += random.Next(2) == 1 ? 1 : -1; } else if (canGoLeft) { square -= 1; } else if (canGoRight) { square += 1; } else { //We've done it all currentTier++; } } else { currentTier++; } } //Now that that part is done, lets add some more paths so we turn this into a graph foreach (CitadelRoom room in rooms) { //For each room, check who is a sibling or immediatly under him. There is a 50% chance of forming a link CitadelRoom[] potentialRooms = GetPathableRooms(rooms, room.TierNumber, room.SquareNumber); foreach (CitadelRoom potentialRoom in potentialRooms) { //Is there a connection already? if (!potentialRoom.Connections.Contains(room.UniqueID)) { if (random.Next(2) == 1) { //add a connection room.Connections.Add(potentialRoom.UniqueID); potentialRoom.Connections.Add(room.UniqueID); } } } } //go through the rooms and set some as wild rooms already foreach (var room in rooms) { if (random.Next(100) > percentageOwned) { //Wild room room.CitadelRoomType = CitadelRoomType.WILD_ROOM; } } //Lets assign the rooms based on the maximum amount. //Some rooms have more probability in certain regions. //So lets divide the rooms in 3 //Favoured - x3 //Other - x2 //Unfavoured - x1 int lowerBoundary = rooms.Count / 3; int upperBoundary = 2 * rooms.Count / 3; var orderedUtilities = rooms.Where (o => o.CitadelRoomType == CitadelRoomType.EMPTY_ROOM).OrderByDescending(o => random.Next(100) * (o.UniqueID > upperBoundary ? 1 : o.UniqueID > lowerBoundary ? 2 : 3)).Where(r => r.CitadelRoomType == CitadelRoomType.EMPTY_ROOM ).ToArray().Take(utilityRooms); foreach (var room in orderedUtilities) { room.CitadelRoomType = CitadelRoomType.UTILITY_ROOM; } //Same thing for treasure rooms var orderedTreasure = rooms.Where (o => o.CitadelRoomType == CitadelRoomType.EMPTY_ROOM).OrderByDescending(o => random.Next(100) * (o.UniqueID > upperBoundary ? 3 : o.UniqueID > lowerBoundary ? 2 : 1)).Where(r => r.CitadelRoomType == CitadelRoomType.EMPTY_ROOM ).Take(treasureRooms); foreach (var room in orderedTreasure) { room.CitadelRoomType = CitadelRoomType.TREASURE_ROOM; } //And guard rooms var orderedGuard = rooms.Where (o => o.CitadelRoomType == CitadelRoomType.EMPTY_ROOM).OrderByDescending(o => random.Next(100) * (o.UniqueID > upperBoundary ? 1 : o.UniqueID > lowerBoundary ? 3 : 2)).Where(r => r.CitadelRoomType == CitadelRoomType.EMPTY_ROOM ).Take(guardRooms); foreach (var room in orderedGuard) { room.CitadelRoomType = CitadelRoomType.GUARD_ROOM; } //Now that that part is done, we put them on the actual grid. //We go for a 15x15 room and connect the items in it. //15x15 - with a gap of 7 between them for tunnels int mapWidth = ((WIDTH + 7) * 20); int mapHeight = ((tiers + 7) * 20); //Create new blocks MapBlock[,] map = new MapBlock[mapWidth, mapHeight]; for (int x = 0; x < map.GetLength(0); x++) { for (int y = 0; y < map.GetLength(1); y++) { map[x, y] = new MapBlock() { Tile = new MapItem() { Coordinate = new MapCoordinate(x, y, 0, DRObjects.Enums.MapType.LOCAL), MayContainItems = false } }; } } LocalMapGenerator gen = new LocalMapGenerator(); LocalMapXMLParser xmlGen = new LocalMapXMLParser(); //Start generating the maps and then stitch them upon the main map foreach (CitadelRoom room in rooms) { MapBlock[,] gennedMap = null; string tag = String.Empty; switch (room.CitadelRoomType) { case CitadelRoomType.EMPTY_ROOM: tag = "Empty Dungeon"; break; case CitadelRoomType.GUARD_ROOM: tag = "Guard Dungeon"; break; case CitadelRoomType.UTILITY_ROOM: tag = "Utility Dungeon"; break; case CitadelRoomType.TREASURE_ROOM: tag = "Treasure Dungeon"; break; case CitadelRoomType.WILD_ROOM: tag = "Empty Dungeon"; break; default: throw new NotImplementedException("Dungeon Room " + room.CitadelRoomType + " not planned for yet."); } //Generate it :) Maplet maplet = xmlGen.ParseMapletFromTag(tag); Actor[] acts = null; MapletActorWanderArea[] wanderAreas = null; MapletPatrolPoint[] patrolPoints = null; MapletFootpathNode[] footPath = null; gennedMap = gen.GenerateMap(25, null, maplet, true, "", OwningFactions.ORCS ,out acts,out wanderAreas,out patrolPoints,out footPath); enemies.AddRange(acts); //Is it a treasure room? if (room.CitadelRoomType == CitadelRoomType.TREASURE_ROOM) { //Generate some loot GenerateLoot(gennedMap, room.TierNumber); } PointOfInterest mapletInterest = null; if (room.CitadelRoomType == CitadelRoomType.GUARD_ROOM || room.CitadelRoomType == CitadelRoomType.TREASURE_ROOM) { //This will be a point of interest. Select a random walkable point in the room and mark the place as such for (int tryAmount = 0; tryAmount < 50; tryAmount++) { //Try for a maximum of 50 times int x = random.Next(gennedMap.GetLength(0)); int y = random.Next(gennedMap.GetLength(1)); if (gennedMap[x, y].Tile.MayContainItems) { //Put this as the point PointOfInterest interest = new PointOfInterest(); interest.Coordinate = new MapCoordinate(x, y, 0, MapType.LOCAL); if (room.CitadelRoomType == CitadelRoomType.GUARD_ROOM) { interest.Type = PointOfInterestType.GUARD_ROOM; } else if (room.CitadelRoomType == CitadelRoomType.TREASURE_ROOM) { interest.Type = PointOfInterestType.TREASURE; } pointsOfInterest.Add(interest); mapletInterest = interest; break; } } } DRObjects.Actor[] roomEnemies = new DRObjects.Actor[] { }; if (room.CitadelRoomType == CitadelRoomType.GUARD_ROOM || room.CitadelRoomType == CitadelRoomType.TREASURE_ROOM) { //Create an amount of enemies - level doesn't matter, we'll regen later gennedMap = gen.GenerateEnemies(gennedMap, random.Next(maxOwnedPopulation), ownerType, out roomEnemies, 10); enemies.AddRange(roomEnemies); } if (room.CitadelRoomType == CitadelRoomType.WILD_ROOM) { //Create an amount of wild enemies - let's get a random type for this room. This will be of level 5. Later we'll have proper wildlife string type = ActorGeneration.GetEnemyType(false); gennedMap = gen.GenerateEnemies(gennedMap, random.Next(maxWildPopulation), type, out roomEnemies, 5); //go through all of room enemies and set them to idle foreach (var enemy in roomEnemies) { enemy.MissionStack.Clear(); enemy.MissionStack.Push(new IdleMission()); } enemies.AddRange(roomEnemies); } //fit her onto the main map int xIncreaser = room.SquareNumber * 20; int yIncreaser = (room.TierNumber * 20) + 3; //Fix the patrol points of any enemies foreach (Actor enemy in roomEnemies.Union(acts)) { if (enemy.MissionStack.Count != 0 && enemy.MissionStack.Peek().MissionType == DRObjects.ActorHandling.ActorMissionType.WANDER) { //Change patrol point MapCoordinate point = (enemy.MissionStack.Peek() as WanderMission).WanderPoint; point.X += xIncreaser; point.Y += yIncreaser; //Change the rectangle x and y too Rectangle rect = (enemy.MissionStack.Peek() as WanderMission).WanderRectangle; rect.X = xIncreaser; rect.Y = yIncreaser; (enemy.MissionStack.Peek() as WanderMission).WanderRectangle = rect; //apparently rectangles are immutable or something } } //Update the point of interest if there is one if (mapletInterest != null) { mapletInterest.Coordinate.X += xIncreaser; mapletInterest.Coordinate.Y += yIncreaser; } for (int x = 0; x < gennedMap.GetLength(0); x++) { for (int y = 0; y < gennedMap.GetLength(1); y++) { map[x + xIncreaser, y + yIncreaser] = gennedMap[x, y]; map[x + xIncreaser, y + yIncreaser].Tile.Coordinate = new MapCoordinate(x + xIncreaser, y + yIncreaser, 0, DRObjects.Enums.MapType.LOCAL); foreach (var item in map[x + xIncreaser, y + yIncreaser].GetItems()) { item.Coordinate = new MapCoordinate(x + xIncreaser, y + yIncreaser, 0, DRObjects.Enums.MapType.LOCAL); } } } //Lets draw the connections - only the ones who's rooms we've drawn yet ItemFactory.ItemFactory factory = new ItemFactory.ItemFactory(); foreach (var connection in room.Connections.Where(c => c < room.UniqueID)) { if (connection == -1) { //Entrance hall! //Create a line of 3 at the bottom and return the coordinates int topEdgeY = yIncreaser; int bottomEdgeXMin = 0 + xIncreaser; int bottomEdgeXMax = gennedMap.GetLength(0) + xIncreaser; //Find the start int xStart = (bottomEdgeXMax - bottomEdgeXMin) / 2 + bottomEdgeXMin; //Set the start point startPoint = new MapCoordinate(xStart + 1, topEdgeY - 2, 0, MapType.LOCAL); //Put the 'leave town' item on it map[startPoint.X, startPoint.Y].ForcePutItemOnBlock(new LeaveTownItem()); int x = xStart; int y = topEdgeY; //go 3 steps down for (int a = 0; a < 3; a++) { for (int x1 = 0; x1 < 3; x1++) { //Draw! map[x + x1, y].Tile = factory.CreateItem("TILES", 25); map[x + x1, y].Tile.Coordinate = new MapCoordinate(x + x1, y, 0, MapType.LOCAL); } y--; //move down } y = topEdgeY; //Walk back do { for (int x1 = 0; x1 < 3; x1++) { //Draw! map[x + x1, y].Tile = factory.CreateItem("TILES", 25); map[x + x1, y].Tile.Coordinate = new MapCoordinate(x + x1, y, 0, MapType.LOCAL); } y++; //move up } while (x >= 0 && y < map.GetLength(1) && !map[x, y].Tile.MayContainItems); //Put the spikes at the entrance int dummy = -1; map[xStart, topEdgeY - 2].ForcePutItemOnBlock(factory.CreateItem(Archetype.MUNDANEITEMS, "spikes", out dummy)); map[xStart + 2, topEdgeY - 2].ForcePutItemOnBlock(factory.CreateItem(Archetype.MUNDANEITEMS, "spikes", out dummy)); continue; } //Identify the room to be connected with var roomToBeConnected = rooms.Where(r => r.UniqueID.Equals(connection)).FirstOrDefault(); //Determine the direction relative to the current room if (roomToBeConnected.SquareNumber > room.SquareNumber) { //RIGHT //Find the rightmost edge of the room and start... somewhere int rightEdgeX = gennedMap.GetLength(0) + xIncreaser; int rightEdgeYMin = 0 + yIncreaser; int rightEdgeYMax = gennedMap.GetLength(1) + yIncreaser; //Pick a start at random int yStart = random.Next(rightEdgeYMax - rightEdgeYMin - 2) + rightEdgeYMin; //Now 'walk' from ystart-ystart+3 until you hit on something which has a block in it int x = rightEdgeX; int y = yStart; while (x < map.GetLength(0) && y < map.GetLength(1) && !map[x, y].Tile.MayContainItems) { for (int y1 = 0; y1 < 3; y1++) { //Draw! map[x, y + y1].Tile = factory.CreateItem("TILES", 25); map[x, y + y1].Tile.Coordinate = new MapCoordinate(x, y + y1, 0, MapType.LOCAL); } x++; //increment x } x = rightEdgeX - 1; //now lets walk backwards too while (x >= 0 && x < map.GetLength(0) && y >= 0 && y < map.GetLength(1) && !map[x, y].Tile.MayContainItems) { for (int y1 = 0; y1 < 3; y1++) { //Draw! map[x, y + y1].Tile = factory.CreateItem("TILES", 25); map[x, y + y1].Tile.Coordinate = new MapCoordinate(x, y + y1, 0, MapType.LOCAL); } x--; //walk back } } else if (roomToBeConnected.SquareNumber < room.SquareNumber) { //LEFT //Find the leftMose edge of the room and start... somewhere int leftEdgeX = xIncreaser; int leftEdgeYMin = 0 + yIncreaser; int leftEdgeYMax = gennedMap.GetLength(1) + yIncreaser; //Pick a start at random int yStart = random.Next(leftEdgeYMax - leftEdgeYMin - 2) + leftEdgeYMin; //Now 'walk' from ystart-ystart+3 until you hit on something which has a block in it int x = leftEdgeX; int y = yStart; do { for (int y1 = 0; y1 < 3; y1++) { //Draw! map[x, y + y1].Tile = factory.CreateItem("TILES", 25); map[x, y + y1].Tile.Coordinate = new MapCoordinate(x, y + y1, 0, MapType.LOCAL); } x--; //decrement x } while (x >= 0 && x < map.GetLength(0) && y >= 0 && y < map.GetLength(1) && !map[x, y].Tile.MayContainItems); x = leftEdgeX + 1; //walk backwards do { for (int y1 = 0; y1 < 3; y1++) { //Draw! map[x, y + y1].Tile = factory.CreateItem("TILES", 25); map[x, y + y1].Tile.Coordinate = new MapCoordinate(x, y + y1, 0, MapType.LOCAL); } x++; //walk back } while (x >= 0 && x < map.GetLength(0) && y >= 0 && y < map.GetLength(1) && !map[x, y].Tile.MayContainItems); } else if (roomToBeConnected.TierNumber < room.TierNumber) { //BOTTOM //Find the bottommost edge of the room and start... somewhere int bottomEdgeY = yIncreaser; int bottomEdgeXMin = 0 + xIncreaser; int bottomEdgeXMax = gennedMap.GetLength(0) + xIncreaser; //Pick a start at random int xStart = random.Next(bottomEdgeXMax - bottomEdgeXMin - 2) + bottomEdgeXMin; //Now 'walk' from xstart-xstart+3 until you hit on something which has a block in it int x = xStart; int y = bottomEdgeY; do { for (int x1 = 0; x1 < 3; x1++) { //Draw! map[x + x1, y].Tile = factory.CreateItem("TILES", 25); map[x + x1, y].Tile.Coordinate = new MapCoordinate(x + x1, y, 0, MapType.LOCAL); } y--; //decrement y } while (x >= 0 && x < map.GetLength(0) && y >= 0 && y < map.GetLength(1) && !map[x, y].Tile.MayContainItems); y = bottomEdgeY + 1; //Walk backwards do { for (int x1 = 0; x1 < 3; x1++) { //Draw! map[x + x1, y].Tile = factory.CreateItem("TILES", 25); map[x + x1, y].Tile.Coordinate = new MapCoordinate(x + x1, y, 0, MapType.LOCAL); } y++; //walk back } while (x >= 0 && x < map.GetLength(0) && y >= 0 && y < map.GetLength(1) && !map[x, y].Tile.MayContainItems); } else if (roomToBeConnected.TierNumber > room.TierNumber) { //TOP - Won't ever happen - but sure //Find the topmost edge of the room and start... somewhere int topEdgeY = yIncreaser + gennedMap.GetLength(1); int bottomEdgeXMin = 0 + xIncreaser; int bottomEdgeXMax = gennedMap.GetLength(0) + xIncreaser; //Pick a start at random int xStart = random.Next(bottomEdgeXMax - bottomEdgeXMin - 2) + bottomEdgeXMin; //Now 'walk' from xstart-xstart+3 until you hit on something which has a block in it int x = xStart; int y = topEdgeY; do { bool holed = false; for (int x1 = 0; x1 < 3; x1++) { if (!holed) { //Have a chance of putting in a hole if (random.Next(8) == 0) { holed = true; continue; //don't put in a tile } } //Draw! map[x + x1, y].Tile = factory.CreateItem("TILES", 25); map[x + x1, y].Tile.Coordinate = new MapCoordinate(x + x1, y, 0, MapType.LOCAL); } y++; //move up } while (x >= 0 && x < map.GetLength(0) && y >= 0 && y < map.GetLength(1) && !map[x, y].Tile.MayContainItems); //walk back y = topEdgeY + 1; do { for (int x1 = 0; x1 < 3; x1++) { //Draw! map[x + x1, y].Tile = factory.CreateItem("TILES", 25); map[x + x1, y].Tile.Coordinate = new MapCoordinate(x + x1, y, 0, MapType.LOCAL); } y--; //move down } while (x >= 0 && x < map.GetLength(0) && y >= 0 && y < map.GetLength(1) && !map[x, y].Tile.MayContainItems); } } } //We need to fix the enemies to conform to the standards ConformEnemies(enemies); enemyArray = enemies.ToArray(); return map; }
public bool HandleClick(int x, int y, Objects.Enums.MouseActionEnum mouseAction, out DRObjects.Enums.ActionType? actionType, out InternalActionEnum? internalActionType, out object[] args, out MapItem item, out DRObjects.MapCoordinate coord, out bool destroy) { Point point = new Point(x, y); item = null; args = null; coord = null; destroy = false; actionType = null; internalActionType = null; if (!visible) { return false; //don't do anything } //If we pressed a stance button, just change it if (this.defensiveStatusRect.Contains(point)) { //Swap stance to defensive attacker.CombatStance = DRObjects.ActorHandling.ActorStance.DEFENSIVE; return true; } else if (this.aggressiveStatusRect.Contains(point)) { //Aggressive attacker.CombatStance = DRObjects.ActorHandling.ActorStance.AGGRESSIVE; return true; } else if (this.normalStatusRect.Contains(point)) { //Normal attacker.CombatStance = DRObjects.ActorHandling.ActorStance.NEUTRAL; return true; } //Where did the user click? if (attackButtonRectangle.Contains(point)) { //Then attack actionType = ActionType.ATTACK; List<object> argumentList = new List<object>(); argumentList.Add(this.attacker); argumentList.Add(this.TargetActor); argumentList.Add(currentAttackLocation); args = argumentList.ToArray(); return true; } //Did they click on something? Change the target if (headRect.Contains(point)) { this.currentAttackLocation = AttackLocation.HEAD; return true; } if (leftArmRect.Contains(point)) { this.currentAttackLocation = AttackLocation.LEFT_ARM; return true; } if (chestRect.Contains(point)) { this.currentAttackLocation = AttackLocation.CHEST; return true; } if (rightArmRect.Contains(point)) { this.currentAttackLocation = AttackLocation.RIGHT_ARM; return true; } if (legRect.Contains(point)) { this.currentAttackLocation = AttackLocation.LEGS; return true; } if (closeRect.Contains(point)) { //Then close it destroy = true; return true; } //Did we click on a special attack? for(int i=0; i < saRects.Length; i++) { var rectangle = saRects[i]; if (rectangle.Contains(x,y)) { //Valid special attack? if (attacker.SpecialAttacks[i] != null && attacker.SpecialAttacks[i].TimeOutLeft == 0) { //Then attack actionType = ActionType.ATTACK; List<object> argumentList = new List<object>(); argumentList.Add(this.attacker); argumentList.Add(this.TargetActor); argumentList.Add(AttackLocation.CHEST); argumentList.Add(attacker.SpecialAttacks[i]); args = argumentList.ToArray(); return true; //Attack! } } } return visible; //If it's visible - block it. Otherwise do nothing }
public bool HandleClick(int x, int y, Objects.Enums.MouseActionEnum mouseAction, out DRObjects.Enums.ActionType? actionType, out DRObjects.Enums.InternalActionEnum? internalActionType, out object[] args, out DRObjects.MapItem item, out DRObjects.MapCoordinate coord, out bool destroy) { actionType = null; internalActionType = null; args = null; coord = null; destroy = false; item = null; //Since this is modal it'll get all clicks. If the user has clicked out of the element, then we can destroy it if (!rect.Contains(x,y)) { destroy = true; } Potion selectedPotion = null; //Determine the potion that was selected foreach(var r in this.ItemRects) { if (r.Rect.Contains(x,y)) { selectedPotion = r.Item as Potion; } } if (selectedPotion == null) { //Never mind return true; } //Otherwise, throw the stuff! //Determine who's in the splashzone var blocks = GameState.LocalMap.GetBlocksAroundPoint(targetCoordinate, 1); List<Actor> victims = new List<Actor>(); foreach(var block in blocks) { victims.AddRange(block.GetItems().Where(i => i.IsActive && i.GetType() == typeof(LocalCharacter)).Select(i => (i as LocalCharacter).Actor)); } //Remove dead ones - just in case victims = victims.Where(v => v.IsAlive).ToList(); actionType = ActionType.THROW_ITEM; args = new object[3] { Actor, victims, selectedPotion }; destroy = true; //Oh, don't forget to discard the potion selectedPotion.InInventory = false; Actor.Inventory.Inventory.Remove(selectedPotion.Category, selectedPotion); return true; //modal }
public bool HandleClick(int x, int y, Objects.Enums.MouseActionEnum mouseAction, out DRObjects.Enums.ActionType? actionType, out DRObjects.Enums.InternalActionEnum? internalActionType, out object[] args, out MapItem itm, out DRObjects.MapCoordinate coord, out bool destroy) { actionType = null; internalActionType = null; args = null; coord = null; destroy = false; itm = null; //Clicked on a context menu item? foreach (var contextMenu in contextMenuChoices) { if (contextMenu.Rect.Contains(x, y)) { //Yes. Perform the action //this.selectedItem.PerformAction(contextMenu.Action, this.CurrentActor, contextMenu.Args); actionType = contextMenu.Action; args = contextMenu.Args; itm = selectedItem; } } //remove the contextual menu this.contextMenu = new Rectangle(0, 0, 0, 0); contextMenuChoices = new List<ContextMenuItem>(); selectedItem = null; for (int i=0; i < categories.Count; i++) { if (categories[i].Contains(x, y)) { //Change category! this.ChosenCategory = i; //remove the contextual menu contextMenu = new Rectangle(0, 0, 0, 0); contextMenuChoices = new List<ContextMenuItem>(); selectedItem = null; //Handled. Naught else return true; } } //Have we clicked on an item ? List<InventoryItemRectangle> allItemBoxes = new List<InventoryItemRectangle>(); allItemBoxes.AddRange(row1Items); allItemBoxes.AddRange(row2Items); allItemBoxes.AddRange(row3Items); foreach (InventoryItemRectangle rect in allItemBoxes) { if (rect.Rect.Contains(x, y)) { //remove the contextual menu contextMenu = new Rectangle(0, 0, 0, 0); contextMenuChoices = new List<ContextMenuItem>(); selectedItem = null; //Does it contain an item? if (rect.Item != null) { //Yes - open contextual menu contextMenu = new Rectangle(x+15, y+15, 0, 0); selectedItem = rect.Item; foreach (var action in rect.Item.GetPossibleActions(this.CurrentActor)) { AddContextMenuItem(action, new object[0] { }, content); } //done return true; } else { return true; //Empty box } } } //Have we clicked on an equipped item? foreach (EquippedItemRectangle rect in equipmentRectangles) { if (rect.Rect.Contains(x, y)) { //remove the contextual menu contextMenu = new Rectangle(0, 0, 0, 0); contextMenuChoices = new List<ContextMenuItem>(); selectedItem = null; //Does it contain an item? if (rect.InventoryItem != null) { //Yes - open contextual menu contextMenu = new Rectangle(x + 15, y + 15, 0, 0); selectedItem = rect.InventoryItem; foreach (var action in rect.InventoryItem.GetPossibleActions(this.CurrentActor)) { AddContextMenuItem(action, new object[0] { }, content); } //done return true; } else { return true; //Empty box } } } return true; }
public bool HandleClick(int x, int y, Objects.Enums.MouseActionEnum mouseAction, out DRObjects.Enums.ActionType? actionType, out DRObjects.Enums.InternalActionEnum? internalActionType, out object[] args, out DRObjects.MapItem item, out DRObjects.MapCoordinate coord, out bool destroy) { actionType = null; args = null; coord = null; destroy = false; internalActionType = null; item = null; if (this.crossRect.Contains(x, y)) { //close it destroy = true; return true; } if (this.takeAllRect.Contains(x, y)) { //Take it, take it all! foreach (var i in this.treasureChest.Contents) { //Do we have an item with the same name in the inventory? var oldItem = GameState.PlayerCharacter.Inventory.Inventory.GetObjectsByGroup(i.Category).Where(g => g.Name.Equals(i.Name)).FirstOrDefault(); if (oldItem != null) { //Instead we increment the total in that item in the inventory oldItem.TotalAmount++; } else { GameState.PlayerCharacter.Inventory.Inventory.Add(i.Category, i); } } //Remove them this.treasureChest.Contents = new List<InventoryItem>(); destroy = true; //and close it return true; } for (int i = 0; i < this.itemRectangles.Count; i++) { if (this.itemRectangles[i].Contains(x, y)) { //Overlap! Put in the description if (this.treasureChest.Contents.Count > i) { InventoryItem inv = this.treasureChest.Contents[i] as InventoryItem; //take it! GameState.PlayerCharacter.Inventory.Inventory.Add(inv.Category, inv); //Remove it this.treasureChest.Contents.RemoveAt(i); if (this.treasureChest.Contents.Count == 0) { //Cleared it out. Close it destroy = true; } } return true; } } return true; }
public bool HandleClick(int x, int y, Objects.Enums.MouseActionEnum mouseAction, out DRObjects.Enums.ActionType? actionType, out InternalActionEnum? internalActionType, out object[] args, out MapItem item, out DRObjects.MapCoordinate coord, out bool destroy) { Point point = new Point(x, y); item = null; actionType = null; args = null; coord = null; destroy = false; internalActionType = null; if (!Visible) { return false; } //Did the user click on one of the choices? foreach (var decision in decisions) { if (decision.Rect.Contains(point)) { //Send the details pertaing to this decision actionType = decision.ActionType; internalActionType = decision.InternalAction; args = decision.Args; destroy = true; //User has made a choice, so close it return true; } } //Not handled. But if it's modal, we expect it to catch all handling if (IsModal()) { return true; } else { return false; } }
public bool HandleClick(int x, int y, Objects.Enums.MouseActionEnum mouseAction, out DRObjects.Enums.ActionType? actionType, out InternalActionEnum? internalActionType, out object[] args, out MapItem item, out DRObjects.MapCoordinate coord, out bool destroy) { Point point = new Point(x, y); item = null; actionType = null; args = null; coord = null; destroy = false; internalActionType = null; if (!Visible) { return false; } if (mouseAction != Objects.Enums.MouseActionEnum.LEFT_CLICK) { return true; } //Did the user click on one of the choices? foreach (var decision in this.currentEvent.Choices) { if (decision.Rect.Contains(point)) { //Decision has been made choicesMade.Add(decision.ChoiceName); //Do we have a next choice? if (decision.NextChoice != null) { //Change the current choice this.currentEvent = decision.NextChoice; this.PerformDrag(0, 0); //force recreation } else { //terminate! Send back that its a multidecision, and the event name and the choices made internalActionType = InternalActionEnum.MULTIDECISION; args = new object[] { this.currentEvent.EventName, this.choicesMade }; destroy = true; } } } //Not handled. But if it's modal, we expect it to catch all handling if (IsModal()) { return true; } else { return false; } }