Place on a tile in a dungeon that contains a part of a puzzle.
Example #1
0
		/// <summary>
		/// Creates new monster group.
		/// </summary>
		/// <param name="name"></param>
		/// <param name="puzzle"></param>
		/// <param name="place"></param>
		/// <param name="spawnPosition"></param>
		public MonsterGroup(string name, Puzzle puzzle, PuzzlePlace place, Placement spawnPosition = Placement.Random)
		{
			_monsters = new List<NPC>();

			this.Name = name;
			this.Puzzle = puzzle;
			this.Place = place;
			_spawnPosition = spawnPosition;
		}
Example #2
0
        /// <summary>
        /// Adds prop to puzzle in place.
        /// </summary>
        /// <param name="place"></param>
        /// <param name="prop"></param>
        /// <param name="positionType"></param>
        public void AddProp(PuzzlePlace place, DungeonProp prop, Placement positionType)
        {
            if (this.Region == null)
            {
                throw new PuzzleException("AddProp outside of OnPuzzleCreate.");
            }

            var pos = place.GetPosition(positionType);

            prop.RegionId = this.Region.Id;
            prop.Info.X   = pos[0];
            prop.Info.Y   = pos[1];
            prop.UpdateShapes();
            prop.Info.Direction = MabiMath.DegreeToRadian(pos[2]);
            prop.Behavior      += PuzzleEvent;

            this.Region.AddProp(prop);
            this.Props[prop.Name] = prop;
        }
Example #3
0
        /// <summary>
        /// Locks place and creates and returns a key for it.
        /// </summary>
        /// <param name="place"></param>
        /// <param name="keyName"></param>
        /// <returns></returns>
        public Item LockPlace(PuzzlePlace place, string keyName)
        {
            if (!place.IsLock)
            {
                throw new PuzzleException("Tried to lock a place that isn't a Lock");
            }

            var doorName = place.GetLockDoor().Name;

            Item key;

            if (place.IsBossLock)
            {
                key = Item.CreateKey(70030, 0xFF0000, doorName);                 // Boss Room Key
            }
            else
            {
                key = Item.CreateKey(70029, place.LockColor, doorName);                 // Dungeon Room Key
            }
            place.LockPlace(key);
            this.Keys[keyName] = key;

            return(key);
        }
Example #4
0
        /// <summary>
        /// Adds key for lock place to a random monster of this group as a drop.
        /// </summary>
        /// <param name="lockPlace"></param>
        public void AddKeyForLock(PuzzlePlace lockPlace)
        {
            var place = lockPlace as PuzzlePlace;

            if (!place.IsLock)
            {
                Log.Warning("PuzzleChest.AddKeyForLock: This place isn't a Lock. ({0})", this.Puzzle.Name);
                return;
            }

            if (this.Count == 0)
            {
                Log.Warning("MonsterGroup.AddKeyForLock: No monsters in group.");
                return;
            }

            if (place.Key == null)
            {
                Log.Warning("MonsterGroup.AddKeyForLock: Place's key is null.");
                return;
            }

            this.AddDrop(place.Key);
        }
Example #5
0
		/// <summary>
		/// This place will precede locked place and contain some means to unlock it.
		/// </summary>
		/// <param name="lockPlace"></param>
		public void DeclareUnlock(PuzzlePlace lockPlace)
		{
			var place = lockPlace as PuzzlePlace;
			if (place == null || place.PlaceIndex == -1)
				throw new PuzzleException("We can't declare unlock");

			this.PlaceIndex = _section.GetUnlock(place);
			_room = _section.Places[PlaceIndex].Room;
			this.IsUnlock = true;

			this.UpdatePosition();
		}
Example #6
0
		/// <summary>
		/// Finds appropriate place to use as unlock place for given locked place.
		/// </summary>
		/// <param name="lockedPlace"></param>
		/// <returns>Index of unlock place in Places list</returns>
		public int GetUnlock(PuzzlePlace lockedPlace)
		{
			var lockedPlaceIndex = lockedPlace.PlaceIndex;
			// Get index of room behind lockedPlace door.
			lockedPlaceIndex = this.Places[lockedPlaceIndex].Room.Neighbor[lockedPlace.DoorDirection].RoomIndex;
			if (lockedPlaceIndex == 0 || lockedPlaceIndex == -1) // should be last room in section.
				lockedPlaceIndex = this.Places.Count;

			List<int> possiblePlacesOnPath = new List<int>();
			List<int> possiblePlacesNotOnPath = new List<int>();
			var deadEnd = -1;
			var deadEndDepth = 0;
			RoomTrait room;
			// places before lockedPlaceIndex are always behind it.
			for (var i = 0; i < lockedPlaceIndex; ++i)
			{
				room = this.Places[i].Room;
				if (!this.Places[i].IsUsed && !room.isLocked && room.RoomType != RoomType.Start)
				{
					// Check is this place have locked doors.
					// Locked places tend to not reserve themselves, so they could share place with some puzzle, like another locked place.
					// But they couldn't be shared with unlock places, because they have to control all doors.
					var haveLockedDoors = false;
					for (var j = 0; j < 4; ++j)
						if (room.DoorType[j] == (int)DungeonBlockType.DoorWithLock && room.Links[j] == LinkType.To)
						{
							haveLockedDoors = true;
							break;
						}
					if (!haveLockedDoors)
					{
						var emptyNeighborCount = 0;
						for (var dir = 0; dir < 4; ++dir)
							if (room.IsLinked(dir) && !room.Neighbor[dir].isReserved)
								emptyNeighborCount++;
						if (emptyNeighborCount < 2)
						{
							if (deadEndDepth < this.Places[i].Depth)
								deadEnd = i;
						}
						if (room.isOnPath)
							possiblePlacesOnPath.Add(i);
						else
							possiblePlacesNotOnPath.Add(i);
					}
				}
			}

			// Chance to not use deepest corner for unlock place.
			if (_rng.GetUInt32(100) < 40)
				deadEnd = -1;

			if (possiblePlacesOnPath.Count == 0 && possiblePlacesNotOnPath.Count == 0)
			{
				// Convert locked place room back to alley if there are no more locked doors.
				room = this.Places[lockedPlace.PlaceIndex].Room;
				room.SetDoorType(lockedPlace.DoorDirection, (int)DungeonBlockType.Alley);
				room.SetPuzzleDoor(null, lockedPlace.DoorDirection);
				var isLockedRoom = room.DoorType.Any(x => (x == (int)DungeonBlockType.DoorWithLock || x == (int)DungeonBlockType.BossDoor));
				if (!isLockedRoom)
				{
					room.isLocked = false;
					room.RoomType = RoomType.Alley;
				}

				// Return locked place door to list on available doors.
				var lockedDoorCandidate = new LockedDoorCandidateNode(room, lockedPlace.DoorDirection, room.RoomIndex);
				_lockedDoorCandidates.AddFirst(lockedDoorCandidate);
				throw new PuzzleException("Out of unlock places.");
			}

			var possiblePlaces = (possiblePlacesNotOnPath.Count > 0 ? possiblePlacesNotOnPath : possiblePlacesOnPath);

			var placeIndex = deadEnd != -1 ? deadEnd : possiblePlaces[(int)_rng.GetUInt32((uint)possiblePlaces.Count)];

			// Walk down from current place to our path and add new possible doors to this._lockedDoorCandidates
			room = this.Places[placeIndex].Room;
			while (room.RoomType != RoomType.Start)
			{
				if (room.isOnPath)
					break;
				var dir = room.GetIncomingDirection();
				room.isOnPath = true;
				room = room.Neighbor[dir];

				// skip reserved doors
				//if (room.ReservedDoor[Direction.GetOppositeDirection(dir)]) continue;
				// skip reserved places
				if (room.isReserved) continue;

				var lockedDoorCandidate = new LockedDoorCandidateNode(room, Direction.GetOppositeDirection(dir), room.RoomIndex);
				_lockedDoorCandidates.AddFirst(lockedDoorCandidate);
			}
			return placeIndex;
		}
Example #7
0
		/// <summary>
		/// Adds key for lock place to a random monster of this group as a drop.
		/// </summary>
		/// <param name="lockPlace"></param>
		public void AddKeyForLock(PuzzlePlace lockPlace)
		{
			var place = lockPlace as PuzzlePlace;
			if (!place.IsLock)
			{
				Log.Warning("PuzzleChest.AddKeyForLock: This place isn't a Lock. ({0})", this.Puzzle.Name);
				return;
			}

			if (this.Count == 0)
			{
				Log.Warning("MonsterGroup.AddKeyForLock: No monsters in group.");
				return;
			}

			this.AddDrop(place.Key);
		}
Example #8
0
 /// <summary>
 /// Creates a new place for the puzzle to use.
 /// </summary>
 /// <param name="name"></param>
 /// <returns></returns>
 public PuzzlePlace NewPlace(string name)
 {
     _places[name] = new PuzzlePlace(_section, this, name);
     return(_places[name]);
 }
Example #9
0
		/// <summary>
		/// Spawns mob in place.
		/// </summary>
		/// <param name="place"></param>
		/// <param name="name"></param>
		/// <param name="group"></param>
		/// <param name="spawnPosition"></param>
		public void AllocateAndSpawnMob(PuzzlePlace place, string name, DungeonMonsterGroupData group, Placement spawnPosition)
		{
			var mob = new MonsterGroup(name, this, place, spawnPosition);
			_monsterGroups.Add(name, mob);

			mob.Allocate(group);
			mob.Spawn();
		}
Example #10
0
		/// <summary>
		/// Adds prop to puzzle in place.
		/// </summary>
		/// <param name="place"></param>
		/// <param name="prop"></param>
		/// <param name="positionType"></param>
		public void AddProp(PuzzlePlace place, DungeonProp prop, Placement positionType)
		{
			if (this.Region == null)
				throw new PuzzleException("AddProp outside of OnPuzzleCreate.");

			var pos = place.GetPosition(positionType);

			prop.RegionId = this.Region.Id;
			prop.Info.X = pos[0];
			prop.Info.Y = pos[1];
			prop.UpdateShapes();
			prop.Info.Direction = MabiMath.DegreeToRadian(pos[2]);
			prop.Behavior += PuzzleEvent;

			this.Region.AddProp(prop);
			this.Props[prop.Name] = prop;
		}
Example #11
0
		/// <summary>
		/// Locks place without a key.
		/// </summary>
		/// <param name="place"></param>
		/// <returns></returns>
		public void LockPlace(PuzzlePlace place)
		{
			if (!place.IsLock)
				throw new PuzzleException("Tried to lock a place that isn't a Lock");

			place.LockPlace();
		}
Example #12
0
		/// <summary>
		/// Locks place and creates and returns a key for it.
		/// </summary>
		/// <param name="place"></param>
		/// <param name="keyName"></param>
		/// <returns></returns>
		public Item LockPlace(PuzzlePlace place, string keyName)
		{
			if (!place.IsLock)
				throw new PuzzleException("Tried to lock a place that isn't a Lock");

			var doorName = place.GetLockDoor().Name;

			Item key;
			if (place.IsBossLock)
				key = Item.CreateKey(70030, 0xFF0000, doorName); // Boss Room Key
			else
				key = Item.CreateKey(70029, place.LockColor, doorName); // Dungeon Room Key

			place.LockPlace(key);
			this.Keys[keyName] = key;

			return key;
		}
Example #13
0
		/// <summary>
		/// Creates a new place for the puzzle to use.
		/// </summary>
		/// <param name="name"></param>
		/// <returns></returns>
		public PuzzlePlace NewPlace(string name)
		{
			_places[name] = new PuzzlePlace(_section, this, name);
			return _places[name];
		}