public void TestIList() { List <int> list = Enumerable.Range(MinValue, MaxValue).ToList(); // Get random values for (int i = 0; i < 100; i++) { int value = list.Random(); Assert.IsTrue(list.Contains(value)); } // Copy list var list2 = new List <int>(list); // Shuffle copy in place list2.Shuffle(); AssertIsShuffled(list, list2); // Returns default on empty collection list.Clear(); Assert.IsTrue(list.Random() == default); // Returns default on null collection list = null; Assert.IsTrue(list.Random() == default); }
void Update() { if (_isEmitting) { if (IsOneShot) { _isEmitting = false; } for (var i = 0; i < SpawnsPerSecond; i++) { var obj = Instantiate(ParticleGameObject); obj.GetComponentInChildren <SpriteRenderer>().sprite = SpriteList.Random(); obj.transform.position = transform.position + new Vector3(0, .1f, 0); obj.transform.SetParent(Hack.Everything.transform); var rigidBody = obj.GetComponent <Rigidbody>(); if (rigidBody != null) { rigidBody.AddForce( new Vector3(Random.Range(-1f, 1f), Random.Range(-1f, 1f), Random.Range(-1f, 1f)) * ParticleForce, ForceMode.Impulse); } } } }
internal ClientDestination(ClientTunnelProvider tp, I2PDestinationInfo dest, bool publishdest) { ClientTunnelMgr = tp; PublishDestination = publishdest; ThisDestination = dest; MyDestination = new I2PDestination(ThisDestination); LeaseSet = new I2PLeaseSet(MyDestination, null, new I2PLeaseInfo(ThisDestination)); IncommingSessions = new ReceivedSessions(ThisDestination.PrivateKey); Destinations = new DestinationSessions((ls, header, inf) => { DebugUtils.LogDebug(string.Format("ClientDestination: Execute: Sending data. TrackingId: {0} ({1}) ack {2}, msg {3}.", inf.TrackingId, inf.KeyType, inf.AckMessageId, header)); var outtunnel = OutboundEstablishedPool.Random(); if (outtunnel == null || ls == null || ls.Leases.Count == 0) { throw new FailedToConnectException("No tunnels available"); } var lease = ls.Leases.Random(); outtunnel.Send( new TunnelMessageTunnel(header, lease.TunnelGw, lease.TunnelId)); }, () => InboundEstablishedPool.Random()); NetDb.Inst.IdentHashLookup.LeaseSetReceived += new IdentResolver.IdentResolverResultLeaseSet(IdentHashLookup_LeaseSetReceived); NetDb.Inst.IdentHashLookup.LookupFailure += new IdentResolver.IdentResolverResultFail(IdentHashLookup_LookupFailure); }
private static List <int> BuildRandomInteractivesSequence() { List <int> interactives = new List <int>(); if (!Mine.Ores.Any()) { return(interactives); } foreach (KeyValuePair <int, int> kv in Mine.Ores) { int ore = kv.Key; int quantity = kv.Value; for (var i = 0; i < quantity; i++) { interactives.Add(ore); } } int nbElements = Mine.Maps.ConvertAll(m => m.ElementIds.Count).Sum(); while (interactives.Count < nbElements) { interactives.Add(interactives.Random()); } while (interactives.Count > nbElements) { interactives.Remove(interactives.Random()); } return(new List <int>(interactives.Shuffle().Shuffle().Shuffle())); }
public Person Create() { var gender = Enum.GetValues(typeof(Gender)).Cast <Gender>().Random(); switch (gender) { case Gender.Female: return(new Person(PronounFactory.Create(gender)) { postfix = femalePostfixes.Random(), name = femaleNames.Random(), rank = femaleRanks.Random(), prefix = femalePrefixes.Random(), }); case Gender.Male: return(new Person(PronounFactory.Create(gender)) { postfix = malePostfixes.Random(), name = maleNames.Random(), rank = maleRanks.Random(), prefix = malePrefixes.Random(), }); default: return(new Person(PronounFactory.Create(gender)) { postfix = malePostfixes.Random(), name = maleNames.Random(), rank = maleRanks.Random(), prefix = malePrefixes.Random(), }); } }
// Start is called before the first frame update void Start() { liver = GetComponent <Liver>(); rigidbody = GetComponent <Rigidbody>(); animator = GetComponentInChildren <Animator>(); scene = FindObjectOfType <Boss>(); position = positions.Random(); }
private IEnumerator SwapPairs(SithLightning lightning) { yield return(new WaitForSeconds(SwapFrequency + Random.Range(0f, SwapDivergence))); lightning.Start = LeftSideLightningNodes.Random(); yield return(new WaitForSeconds(SwapFrequency + Random.Range(0f, SwapDivergence))); lightning.End = RightSideLightningNodes.Random(); StartCoroutine(SwapPairs(lightning)); }
public void ListRandom_returns_different_value_for_different_seed(int seed1, int seed2) { List <int> exampleList = new List <int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 }; int firstRandomElement = exampleList.Random <int>(new System.Random(seed1)); int secondRandomElement = exampleList.Random <int>(new System.Random(seed2)); Assert.AreNotEqual(firstRandomElement, secondRandomElement); }
/// <summary> /// A co-routine that shows the UI and returns the selected skill as last return value /// </summary> /// <returns></returns> public IEnumerator ChoosePlayerSkill() { //TODO: implement ExecutePlayerTurn // Show UI // Wait for player to select a skill click //Return the chosen skill var result = Globals.Instance.Skills[Skillset.Random()]; yield return(result); //throw new NotImplementedException(); }
void Start() { currentLetter = alphabet.Random(); tickDestination = new FloatRange(0.1f, 2.5f).RandomValue(); hex = ColorUtility.ToHtmlStringRGBA(new Color( new FloatRange(0.5f, 1).RandomValue(), new FloatRange(0.5f, 1).RandomValue(), new FloatRange(0.5f, 1).RandomValue(), 1 )); }
public void ServiceRandomTest() { var services = new List <ServiceAddress> { new ServiceAddress { Weight = 3 }, new ServiceAddress { Weight = 2 }, new ServiceAddress { Weight = 1 } }; var dict = new Dictionary <double, int>(); for (var i = 0; i < 200; i++) { var service = services.Random(); if (dict.ContainsKey(service.Weight)) { dict[service.Weight]++; } else { dict[service.Weight] = 1; } } Console.WriteLine(JsonConvert.SerializeObject(dict)); }
public Payload GetPayloadWithMostVotes() { _dataAccessMutex.WaitOne(); var topVotes = -1; var topCategories = new List <int>(); for (var i = 0; i < 4; i++) { if (_votes[i].Count >= topVotes) { topVotes = _votes[i].Count; topCategories.Clear(); } if (_votes[i].Count == topVotes) { topCategories.Add(i); } } var result = _options[topCategories.Random(_random)]; _dataAccessMutex.ReleaseMutex(); return(result); }
void fighter_OnDamageTaken(Fighter fighter, Damage obj) { List <Fighter> fighters = Fighter.Fight.GetAllFighters(); fighters.Remove(Fighter); fighters.Random().Heal(Fighter, obj.Delta); }
public void SpawnEntities() { var freeUpperCells = new List <int>(); var map = FieldModel.GenerateEntityMap(); for (int i = 0; i < FieldDimensionModel.Colls; i++) { if (map[i, FieldDimensionModel.Rows - 1] == null) { freeUpperCells.Add(i); } } var newEntities = new List <IEntityModel>(); var freeRandomCells = freeUpperCells.RandomRange((uint)Math.Min(ConfigModel.MaxSpawnUpperCount, freeUpperCells.Count)); GameObject lastSpawnedPrefab = null; foreach (var freeRandomCell in freeRandomCells) { var newEntity = SpawnEntity(freeRandomCell, (int)(FieldDimensionModel.Rows - 1), ref lastSpawnedPrefab); newEntities.Add(newEntity); lastSpawnedPrefab = null; } if (FieldModel.MovableEntity != null) { var movableController = EntityMapperService.GetController(FieldModel.MovableEntity); movableController?.SetActive(false); } FieldModel.MovableEntity = newEntities.Random(); var activEntityController = EntityMapperService.GetController(FieldModel.MovableEntity); activEntityController.SetActive(true); }
public static string RandomString(int minLength = 0, int maxLength = int.MaxValue, bool allowLetters = true, bool allowNumbers = true, bool allowSpecialChars = true, bool allowSpaces = true) { var randLength = rand.Next(minLength, maxLength); var sb = new StringBuilder(); var values = new List <char>(); if (allowLetters) { values.AddRange(letters); } if (allowNumbers) { values.AddRange(numbers); } if (allowSpecialChars) { values.AddRange(special); } if (allowSpaces) { values.AddRange(space); } for (var i = 0; i < randLength; i++) { sb.Append(values.Random()); } return(sb.ToString()); }
public void Empty_List_Returns_Default() { var source = new List <string>(); var actual = source.Random(); Assert.IsNull(actual); }
public Encounter GetEncounter(int ownerIndex) { var valid = new List <DungeonEncounter>(); int priority = 0; foreach (var dungeonMonster in dungeon.monsters) { if (dungeonMonster.min <= dungeon.currentLevel && dungeonMonster.max >= dungeon.currentLevel && dungeonMonster.priority >= priority) { if (dungeonMonster.priority > priority) { priority = dungeonMonster.priority; valid.Clear(); } valid.Add(dungeonMonster); } } var choosen = valid.Random(); var encounter = DungeonFactory.CreateEncounter(choosen.monsters, ownerIndex); return(encounter); }
async Task StartBotGifts() { RiftBot.Log.Debug("Gifts are on the way.."); var users = await DB.Cooldowns.GetBotRespectedUsersAsync(); if (users.Count == 0) { RiftBot.Log.Debug("No users with bot respect, rescheduling."); InitTimer(); return; } foreach (var userId in users) { if (!IonicHelper.GetGuildUserById(Settings.App.MainGuildId, userId, out var sgUser)) { continue; } var reward = AvailableRewards.Random(); await rewardService.DeliverToAsync(userId, reward); } await messageService.SendMessageAsync("yasuo-botrespect-success", Settings.ChannelId.Chat, null); RiftBot.Log.Debug("Finished sending gifts"); InitTimer(); }
public static string GetIdleDialogue(string id) { string ret = null; TextAsset ta = Assets.Dialogue[id]; using (StringReader reader = new StringReader(ta.text)) { while (ret != "%%% Idle") { ret = reader.ReadLine(); } // Read past empty line reader.ReadLine(); List <string> options = new List <string>(); // Read until next empty line string s; while ((s = reader.ReadLine()) != "") { options.Add(s); } ret = options.Random(); } return(ret); }
public static Grid On(Grid grid) { foreach (var row in grid.EachRow()) { var run = new List <Cell>(); foreach (var cell in row) { run.Add(cell); var closeOut = cell.East == null || (cell.North != null && rand.Next(2) == 0); if (closeOut) { var member = run.Random(); if (member.North != null) { member.Link(member.North); } run.Clear(); } else { cell.Link(cell.East); } } } return(grid); }
public async Task <SpeechletResponse> RespondAsync() { // it's full and/or running so update status await this._service.UpdateStatusAsync(this._session.User.Id, new RunningStatus()); // build message var salutations = new List <string>() { "Thanks for letting me know.", "Don't be shy when it's time to unload!", "Splish-splash your dishes are taking a bath." }; string text = $"Got it. {salutations.Random()}"; // respond back var response = new SpeechletResponse { OutputSpeech = new PlainTextOutputSpeech() { Text = text }, Card = new SimpleCard() { Title = "Dishwasher Start", Content = text }, ShouldEndSession = false }; return(response); }
public static Grid On(Grid grid) { foreach (var row in grid.EachRow()) { var run = new List<Cell>(); foreach(var cell in row) { run.Add(cell); var closeOut = cell.East == null || (cell.North != null && rand.Next(2) == 0); if (closeOut) { var member = run.Random(); if (member.North != null) { member.Link(member.North); } run.Clear(); } else { cell.Link(cell.East); } } } return grid; }
void GenerateRules() { system.rules.Clear(); int nbOfRules = Random.Range(1, LSystem.variables.Length); List <Module> variables = new List <Module>((Module[])LSystem.variables.Clone()); Module[] precursors = new Module[nbOfRules]; for (int i = 0; i < nbOfRules; i++) { Module precursor = variables.Random(); variables.Remove(precursor); precursors[i] = precursor; int ruleLength = Random.Range(1, 10); List <Module> output = new List <Module>(); //TODO make rule take into account input parameters ? for (int j = 0; j < ruleLength; j++) { Module randomModule = new Module(LSystem.variables.Random()); for (int k = 0; k < randomModule.parameters.Length; k++) { randomModule.parameters[k] = Random.Range(0f, 360f); } output.Add(randomModule); } system.rules.Add(precursor, output.ToArray()); } system.axiom = precursors.Random(); }
void OnSceneLoadStart(EventData data) { if (loader != null) { Debug.LogError("Cant display LoadingBar for 2 scenes"); return; } bool needUI = (bool)data?["needUI"]; if (!needUI) { return; } sceneId = (int)(data.Data?["id"] ?? -1); loader = data.Data?["loader"] as AsyncOperation; if (sceneId == -1 || loader == null) { Debug.LogError("LoadingBar data does not contains all necessary arguments"); return; } bool needDelay = (bool)data?["uiNeedDelay"]; loadingBarRoutine = StartCoroutine(needDelay ? LoadingBarUpdateWithDelay() : LoadingBarUpdate()); tipText.text = "TIP: " + tips.Random(); EnableCanvasGroup(); }
/// <summary> /// Returns a random element from this list and removes the first occurrence of the random element from this list. /// </summary> public static T GetRandomAndRemove <T>(this List <T> list) { T item = list.Random(); list.Remove(item); return(item); }
/// <summary> /// Получить текст /// </summary> /// <returns></returns> public TextData Get() { TextData result = null; List <TextData> activeList = OnlyActual(first, active); //List<TextData> activeList = active; if (active.Count > 0) { result = activeList.Random(); } else { GameText.AddType(reserveType); return(GameText.Get(reserveType)); } active.Remove(result); first.Add(result.text[0].ToString()); notActive.Add(result); return(result); }
/// <summary> /// Get a value from the data source. /// </summary> /// <param name="generateContext">The generate context.</param> /// <returns> /// A new value from the data source. /// </returns> public override object NextValue(IGenerateContext generateContext) { // random card type var type = _cardTypes.Random(p => p.Weight); return(GenerateNumber(type)); }
public static List <BlueprintUnit> SelectUnits(int cr, UnitTag tag) { int minCR = cr - 6; List <BlueprintUnit> list = BlueprintRoot.Instance.RE.UnitsForRandomEncounters.Where <BlueprintUnit>((Func <BlueprintUnit, bool>)(u => OwlcatRESelector.ContainsTag(u.GetComponent <AddTags>(), tag))).Where <BlueprintUnit>((Func <BlueprintUnit, bool>)(u => OwlcatRESelector.GetCR(u) >= minCR)).ToList <BlueprintUnit>(); int xp = OwlcatRESelector.GetXp(cr); int maxTotalXp = OwlcatRESelector.GetXp(cr + 1); int currentXp = 0; List <BlueprintUnit> blueprintUnitList = new List <BlueprintUnit>(); while (currentXp < xp) { list.RemoveAll((Predicate <BlueprintUnit>)(u => OwlcatRESelector.GetXp(u) > maxTotalXp - currentXp)); if (list.Count != 0) { BlueprintUnit unit = list.Random <BlueprintUnit>(); currentXp += OwlcatRESelector.GetXp(unit); blueprintUnitList.Add(unit); } else { break; } } return(blueprintUnitList); }
public void TestCreateProcessCheckBox() { List <string> optionList = OptionFieldHelper.GetOptionList(Enums.Options.ProcessClose); Process resource = CreateProcessWithPhase(); resource.Close = new Option() { ActualXMLTag = optionList.Random() }; string id = PublicApiAdapter.CreateAdapterForDefaultConnection().WriteSuccess(resource, cleanupAction: null); int resourceId = -1; bool parsed = Int32.TryParse(id, out resourceId); Assert.IsTrue(parsed); Assert.IsTrue(resourceId > 0, string.Format(Enums.Message.CREATE_RESOURCE_ENTRY_FAILED, "Process")); PublicAPISetUp.ListProcessId.Add(id); //Verify data Dictionary <string, object> fields = new Dictionary <string, object>() { { "Process.P_Close", (resource.Close as Option).ActualXMLTag }, }; VerifyFieldData(id, fields); }
public void Hit() { cinemachineImpulse.GenerateImpulse(); if (currentBlockPoints > 0) { currentBlockPoints--; } else { if (!collectibles.IsEmpty()) { Collectible remove = collectibles.Random(); collectibles.Remove(remove); remove.gameObject.SetActive(false); } } for (int i = shields.Count - 1; i >= 0; i--) { if (shields[i].gameObject.activeSelf) { shields[i].GetComponent <Animator>()?.SetTrigger("Destruction"); StartCoroutine(DeactivteAfterDuration(shields[i].gameObject, shieldDestructionDuration)); break; } } }
private static List <Vector> CreateGeneration(NodeGrid nodeGrid, List <Node> startingNodes) { const int GEN_SIZE = 50; const int STEPS = 5; var gen = new List <Vector>(); for (var i = 0; i < GEN_SIZE; i++) { var start = startingNodes.Random(); var vector = new Vector(start.Position, start.Position, null); for (var j = 0; j < STEPS; j++) { vector = vector .GenerateAllNextMoves() .Where(m => nodeGrid.IsValidNode(m.End)) ?.Random(); if (vector == null) { break; } } if (vector != null) { gen.Add(vector); } } return(gen); }
public Color RandomNeutralColor() { var lightGreen = new ColorHSV(132f, 0.8f, 1.0f).ToColor(); var lime = new ColorHSV(0.95f, 0.866f, 1.0f).ToColor(); var neutrals = new List<Color>() { lightGreen, lime }; var neutralColor = neutrals.Random(); return neutralColor; }
private static void GenerateClicks(List<int> articles, List<string> users) { Parallel.ForEach(articles, new ParallelOptions { MaxDegreeOfParallelism = 30 }, articleId => { var stopWatch = new Stopwatch(); stopWatch.Start(); var random = new Random(); var viewCount = random.Next(50, 1000); var acrticlesView = new List<StatiscticArticleView>(); Console.WriteLine("Proccessing Clicks for ArticleId: {0}, Clicks count: {1}", articleId, viewCount); for (int i = 0; i < viewCount; i++) { acrticlesView.Add(new StatiscticArticleView { ArticleId = articleId, Time = DateTime.UtcNow.AddDays(0 - random.Next(5, 100)).AddHours(0 - random.Next(0, 24)).AddMinutes(0 - random.Next(0, 60)), UserId = random.Next(0, 100) > 15 ? users.Random() : null }); } try { using (var context = new ApplicationDbContext()) { var commentEnity = (DbSet<StatiscticArticleView>)context.StatiscticArticleViews; commentEnity.AddRange(acrticlesView); context.SaveChanges(); } } catch (Exception exception) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("ERROR Proccessing Clicks for ArticleId: {0}", articleId); Console.WriteLine(exception.Message); if (exception.InnerException != null) { Console.WriteLine(exception.InnerException.Message); } Console.ResetColor(); } stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; var elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}", ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds / 10); Console.WriteLine("Done with article id {0} time spend {1}", articleId, elapsedTime); }); }
private static void GenerateArticles(List<string> users) { var random = new Random(); Parallel.For(0, 3000, new ParallelOptions {MaxDegreeOfParallelism = 30}, index => { using (var context = new ApplicationDbContext()) { var articles = new List<Article>(); var tags = context.Tags.ToList(); for (var i = 0; i < 10; i++) { var article = new Article(); article.Tags.Add(tags.Random()); article.Tags.Add(tags.Random()); article.Header = SeedExtensions.Headers.Random(); article.TeaserText = SeedExtensions.TeaserTexts.Random(); article.Body = SeedExtensions.Body; article.CreatedDate = DateTime.UtcNow.AddDays(0 - random.Next(5, 100)); article.IsPublished = random.Next(0, 100) > 15; article.AuthorId = users.Random(); article.Stamp = Guid.NewGuid(); articles.Add(article); } ((DbSet<Article>) context.Articles).AddRange(articles); try { Console.WriteLine("Saving categories index {0}, count {1}", index, articles.Count()); context.SaveChanges(); } catch (Exception exception) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("ERROR Proccessing Clicks for ArticleId: {0}", index); Console.WriteLine(exception.Message); if (exception.InnerException != null) { Console.WriteLine(exception.InnerException.Message); } Console.ResetColor(); } } }); }
public static Grid On(Grid grid) { foreach (Cell cell in grid) { var neighbors = new List<Cell>(); if (cell.North != null) neighbors.Add(cell.North); if (cell.East != null) neighbors.Add(cell.East); if (neighbors.Any()) { cell.Link(neighbors.Random()); } } return grid; }
public void GettingRepeatedlyRandomItemFromListReturnsItemsWithUniformDistribution() { IList<int> list = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; int count = 10000; IDictionary<int, int> extracted = new Dictionary<int, int>(); foreach (int i in list) { extracted.Add(i, 0); } for (int i = 0; i < count; i++) { int rnd = list.Random(); extracted[rnd] =extracted[rnd] + 1; } int perfectDistributionCount = count / list.Count; foreach (int i in extracted.Keys) { Assert.True(extracted[i] > 0.8 * perfectDistributionCount); Assert.True(extracted[i] < 1.2 * perfectDistributionCount); } }
public void Initialize() { Native.Document.body.style.padding = "0"; Native.Document.body.style.margin = "0"; var Images = new Dictionary<string, IHTMLImage>(); var ImagesLoaded = default(Action); Func<string, IHTMLImage> CloneImage = name => (IHTMLImage)Images[name].cloneNode(false); var Zoom = Data.Zoom.ToDouble(); var ControlSize = new ZoomedPoint { Z = Zoom, X = Data.ControlSize.Xint, Y = Data.ControlSize.Yint }; Control.style.SetSize(ControlSize.ZoomedXint, ControlSize.ZoomedYint); Control.style.backgroundColor = Data.BackgroundColor; Control.style.color = Data.TextColor; Control.AttachAsNextOrToDocument(null); Control.style.position = IStyle.PositionEnum.relative; Action LoadImages = delegate { Data.Sprites.ForEach( i => { Images[i.Value] = i.ImageValue; } ); ImagesLoaded(); }; ImagesLoaded = delegate { var ClientRectPos = new ZoomedPoint { Z = Zoom, X = Data.ClientRect.From.Xint, Y = Data.ClientRect.From.Yint }; var ClientRectSize = new ZoomedPoint { Z = Zoom, X = Data.ClientRect.Size.Xint, Y = Data.ClientRect.Size.Yint }; var ContentLayer = new IHTMLDiv(); ContentLayer.style.backgroundColor = Data.ClientRectColor; ContentLayer.style.overflow = IStyle.OverflowEnum.hidden; ContentLayer.style.SetLocation( ClientRectPos.ZoomedXint, ClientRectPos.ZoomedYint, ClientRectSize.ZoomedXint, ClientRectSize.ZoomedYint ); ContentLayer.AttachTo(Control); //var r1 = CloneImage("room 001").AttachTo(ContentLayer); //r1.style.SetLocation(0, 0, ClientRectSize.ZoomedXint, ClientRectSize.ZoomedYint); Func<string, IHTMLImage> CreateRoomImage = name => { var r2 = CloneImage(name); r2.AttachTo(ContentLayer); var r2_Zoom = new ZoomedPoint { Z = Zoom, X = Images[name].width, Y = Images[name].height }; r2.Hide(); r2.style.SetLocation(0, 0, r2_Zoom.ZoomedXint, r2_Zoom.ZoomedYint); return r2; }; var KnownRooms = new List<IHTMLImage>(); KnownRooms.AddRange( new [] { CreateRoomImage("room 001"), CreateRoomImage("room 002"), CreateRoomImage("room 024"), CreateRoomImage("room 031"), CreateRoomImage("room 032"), } ); var CurrentRoom = KnownRooms.Random(); CurrentRoom.Show(); Action<double> SetClipTo = percentage => { var x = (ClientRectSize.ZoomedX * percentage / 2).ToInt32(); var y = (ClientRectSize.ZoomedY * percentage / 2).ToInt32(); var clip = new CSSClip { Left = x, Top = y, Right = (ClientRectSize.ZoomedX - x).ToInt32(), Bottom = (ClientRectSize.ZoomedY - y).ToInt32() }; Console.WriteLine(percentage + " clip: " + clip); ContentLayer.style.clip = clip; }; //ContentLayer.style.clip = "rect(15px auto auto 15px)"; //var timer = new ScriptCoreLib.JavaScript.Runtime.Timer( // delegate // { // var p = (Math.Sin(DateTime.Now.Ticks) + 1) / 2; // Console.WriteLine("p: " + p); // SetClipTo(p); // } // , 0, 200); //var pc = 50; //var px = 200; //Action<double> pChange = i => { px += (i * pc).ToInt32(); timer.StartInterval(px); }; Action<Action, Action> FadeOut = (Starting, Stopping) => new LinearTimeTween { Length = 300, Starting = Starting, Stopping = Stopping, Changed = t => SetClipTo(t), Percision = 20 }.Start(); Action<Action, Action> FadeIn = (Starting, Stopping) => new LinearTimeTween { Length = 300, Starting = Starting, Stopping = Stopping, Changed = t => SetClipTo(1d - t), Percision = 20 }.Start(); var kbd = new KeyboardEvents { Enabled = true }; kbd.left += ev => FadeOut( () => kbd.Enabled = false, () => { CurrentRoom.Hide(); CurrentRoom = KnownRooms.Previous(i => CurrentRoom == i); CurrentRoom.Show(); //r1.Hide(); //r2.Show(); FadeIn(null, () => kbd.Enabled = true); } ); kbd.right += ev => FadeOut( () => kbd.Enabled = false, () => { CurrentRoom.Hide(); CurrentRoom = KnownRooms.Next(i => CurrentRoom == i); CurrentRoom.Show(); FadeIn(null, () => kbd.Enabled = true); } ); Native.Document.onkeydown += kbd; Native.Document.onmousedown += ev => FadeOut( () => kbd.Enabled = false, () => { CurrentRoom.Hide(); CurrentRoom = KnownRooms.Next(i => CurrentRoom == i); CurrentRoom.Show(); FadeIn(null, () => kbd.Enabled = true); } ); /* var div1 = SpawnDiv(Images, false); div1.style.backgroundColor = Color.Yellow; div1.AttachTo(ClientRect); div1.style.SetLocation(4, 4, 100, 100); var div2 = SpawnDiv(Images, true); div2.style.backgroundColor = Color.Gray; div2.AttachTo(ClientRect); div2.style.SetLocation(100, 4, 100, 100); */ }; LoadImages(); }
public void GettingRandomItemFromEmptyListReturnsNull() { IList<string> list = new List<string>(); Assert.Null(list.Random()); }
public void OnNudge(Actor self, Actor nudger) { /* initial fairly braindead implementation. */ if (self.Owner.Stances[nudger.Owner] != Stance.Ally) return; /* don't allow ourselves to be pushed around * by the enemy! */ if (!self.IsIdle) return; /* don't nudge if we're busy doing something! */ // pick an adjacent available cell. var availCells = new List<int2>(); var notStupidCells = new List<int2>(); //cells that we could enter if the mobile occupants left for( var i = -1; i < 2; i++ ) for (var j = -1; j < 2; j++) { var p = toCell + new int2(i, j); if (p != self.Location) { if (CanEnterCell(p)) availCells.Add(p); else if (CanEnterCell(p, null, false) && p != nudger.Location) notStupidCells.Add(p); } } var moveTo = availCells.Any() ? availCells.Random(self.World.SharedRandom) : notStupidCells.Any() ? notStupidCells.Random(self.World.SharedRandom) : (int2?)null; if (moveTo.HasValue) { self.CancelActivity(); if (self.Owner == self.World.LocalPlayer) self.World.AddFrameEndTask(w => { var line = self.TraitOrDefault<DrawLineToTarget>(); if (line != null) line.SetTargetSilently(self, Target.FromCell(moveTo.Value), Color.Green); }); self.QueueActivity(new Move(moveTo.Value, 0)); } }
public static IEnumerable<Person> GeneratePeople(string connectionString, int gameId, int count = 1) { var personInsert = new SqlInsertStatement(connectionString) .InsertInto("dbo.BZ_Person") .Column("GameId", gameId) .Column("GenderId") .Column("FirstName") .Column("LastName") .Column("Birthday") .Column("RetirementDate") .Column("PersonalityId", 1); for (var index = 0; index < count; index++) { var gender = (int)Utilities.GetRandomValue(Gender.None); var first = Utilities.GetRandomString(16).Replace("'", "''"); var last = Utilities.GetRandomString(16).Replace("'", "''"); var birthday = Utilities.GetRandomDate(); var retirement = birthday.AddYears(Utilities.GetRandomInt(65, 85)); var intensity = Utilities.GetRandomDecimal(0, 1); personInsert.Values() .Value("GenderId", gender) .Value("FirstName", first) .Value("LastName", last) .Value("Birthday", birthday) .Value("RetirementDate", retirement); } personInsert.Execute(); var select = new SqlSelectStatement(connectionString); select.Select("Id") .Select("GenderId") .Select("FirstName") .Select("LastName") .Select("Birthday") .From("BZ_Person") .WhereEquals("GameId", gameId); var output = select.ExecuteComplex<Person>(); var skillIds = new SqlSelectStatement(connectionString) .Select("Id") .From("dbo.BZ_Skill_Definition") .Execute<int>(); var skillInsert = new SqlInsertStatement(connectionString) .InsertInto("dbo.BZ_Person_Skill") .Column("PersonId") .Column("SkillDefinitionId") .Column("Value") .Column("LearnRate") .Column("ForgetRate"); var skillsProperty = typeof(Person).GetProperty("Skills"); foreach (var person in output) { var remainingSkillIds = new List<int>(skillIds); var skills = new List<Skill>(); var skillCount = Utilities.GetRandomInt(1, remainingSkillIds.Count); while (skillCount-- > 0) { var skill = new Skill { ForgetRate = Utilities.GetRandomDecimal(0, 10), LearnRate = Utilities.GetRandomDecimal(0, 10), Value = Utilities.GetRandomDecimal(0, 255), SkillDefinition = new SkillDefinition { Id = (byte)remainingSkillIds.Random() } }; remainingSkillIds.Remove(skill.SkillDefinition.Id); skillInsert.Values() .Value("PersonId", person.Id) .Value("SkillDefinitionId", skill.SkillDefinition.Id) .Value("Value", skill.Value) .Value("LearnRate", skill.LearnRate) .Value("ForgetRate", skill.ForgetRate); skills.Add(skill); } skillsProperty.SetValue(person, skills); } skillInsert.Execute(); return output; }
/// <summary> /// Uses WM, attacking targets. /// </summary> /// <param name="attacker"></param> /// <param name="skill"></param> /// <param name="targetAreaId"></param> /// <param name="unkInt1"></param> /// <param name="unkInt2"></param> public void Use(Creature attacker, Skill skill, long targetAreaId, int unkInt1, int unkInt2) { var range = this.GetRange(attacker, skill); var targets = attacker.GetTargetableCreaturesInRange(range, TargetableOptions.AddAttackRange); // Check targets if (targets.Count == 0) { Send.Notice(attacker, Localization.Get("There isn't a target nearby to use that on.")); Send.SkillUseSilentCancel(attacker); return; } // Create actions var cap = new CombatActionPack(attacker, skill.Info.Id); var aAction = new AttackerAction(CombatActionType.SpecialHit, attacker, targetAreaId); aAction.Set(AttackerOptions.Result); aAction.Stun = CombatMastery.GetAttackerStun(attacker.AverageKnockCount, attacker.AverageAttackSpeed, true); cap.Add(aAction); var survived = new List<Creature>(); var rnd = RandomProvider.Get(); // Check crit var crit = false; if (attacker.Skills.Has(SkillId.CriticalHit, SkillRank.RF)) crit = (rnd.Next(100) < attacker.GetTotalCritChance(0)); // Handle all targets foreach (var target in targets) { target.StopMove(); var tAction = new TargetAction(CombatActionType.TakeHit, target, attacker, skill.Info.Id); tAction.Delay = 300; // Usually 300, sometimes 350? // Calculate damage var damage = attacker.GetRndTotalDamage(); damage *= skill.RankData.Var1 / 100f; // Elementals damage *= attacker.CalculateElementalDamageMultiplier(target); // Crit bonus if (crit) CriticalHit.Handle(attacker, 100, ref damage, tAction); // Handle skills and reductions SkillHelper.HandleDefenseProtection(target, ref damage); SkillHelper.HandleConditions(attacker, target, ref damage); Defense.Handle(aAction, tAction, ref damage); ManaShield.Handle(target, ref damage, tAction); HeavyStander.Handle(attacker, target, ref damage, tAction); // Clean Hit if not defended nor critical if (tAction.SkillId != SkillId.Defense && !tAction.Has(TargetOptions.Critical)) tAction.Set(TargetOptions.CleanHit); // Take damage if any is left if (damage > 0) target.TakeDamage(tAction.Damage = damage, attacker); // Knock down on deadly if (target.Conditions.Has(ConditionsA.Deadly)) { tAction.Set(TargetOptions.KnockDown); tAction.Stun = CombatMastery.GetTargetStun(attacker.AverageKnockCount, attacker.AverageAttackSpeed, true); } // Finish if dead, knock down if not defended if (target.IsDead) tAction.Set(TargetOptions.KnockDownFinish); else if (tAction.SkillId != SkillId.Defense) tAction.Set(TargetOptions.KnockDown); // Anger Management if (!target.IsDead) survived.Add(target); // Stun and shove if not defended if (target.IsDead || tAction.SkillId != SkillId.Defense || target.Conditions.Has(ConditionsA.Deadly)) { tAction.Stun = CombatMastery.GetTargetStun(attacker.AverageKnockCount, attacker.AverageAttackSpeed, true); target.Stability = Creature.MinStability; attacker.Shove(target, KnockbackDistance); } // Add action cap.Add(tAction); } // Update current weapon SkillHelper.UpdateWeapon(attacker, targets.FirstOrDefault(), ProficiencyGainType.Melee, attacker.RightHand, attacker.LeftHand); // Only select a random aggro if there is no aggro yet, // WM only aggroes one target at a time. if (survived.Count != 0 && attacker.Region.CountAggro(attacker) < 1) { var aggroTarget = survived.Random(); aggroTarget.Aggro(attacker); } // Reduce life in old combat system if (!AuraData.FeaturesDb.IsEnabled("CombatSystemRenewal")) { // Default reduction is 10%, it's reduced to 2% if attacker // has less max life than the rate is set to. var lifeReducationRate = skill.RankData.Var2; if (attacker.LifeMax < lifeReducationRate) lifeReducationRate /= 5; var amount = attacker.LifeMax / 100f * lifeReducationRate; attacker.ModifyLife(-amount); // TODO: Invincibility } // Spin it~ Send.UseMotion(attacker, 8, 4); cap.Handle(); Send.SkillUse(attacker, skill.Info.Id, targetAreaId, unkInt1, unkInt2); skill.Stacks = 0; }
CPos ChooseRallyLocationNear(Actor self, CPos startPos) { List<CPos> possibleRallyPoints = new List<CPos>(); if (self.Info.Name.Equals("spen") || self.Info.Name.Equals("syrd")) possibleRallyPoints = world.FindTilesInCircle(startPos, 16).Where(a => world.GetTerrainType(new CPos(a.X, a.Y)).Equals("Water")).ToList(); else possibleRallyPoints = world.FindTilesInCircle(startPos, 8).Where(IsRallyPointValid).ToList(); if (possibleRallyPoints.Count == 0) return startPos; return possibleRallyPoints.Random(random); }
public void AddPillars(int percent_chance_per_room) { //currently does 50% 'pillar', 25% 'statue', and 25% 'other', where relevant. ForEachRectangularRoom((start_r,start_c,end_r,end_c) => { if(PercentChance(percent_chance_per_room)){ int height = end_r - start_r + 1; int width = end_c - start_c + 1; if(height > 3 || width > 3){ List<PillarArrangement> layouts = new List<PillarArrangement>(); if(height % 2 == 1 && width % 2 == 1){ layouts.Add(PillarArrangement.Single); } if((height % 2 == 1 || width % 2 == 1) && height != 4 && width != 4){ layouts.Add(PillarArrangement.Row); } if(height >= 5 && width >= 5){ layouts.Add(PillarArrangement.Corners); } if(height > 2 && width > 2 && height != 4 && width != 4){ layouts.Add(PillarArrangement.Full); } if((width % 2 == 1 && width >= 5) || (height % 2 == 1 && height >= 5)){ layouts.Add(PillarArrangement.StatueEdges); } if(layouts.Count == 0 || CoinFlip()){ //otherwise they're too common layouts.Add(PillarArrangement.StatueCorners); } if(layouts.Count > 0){ CellType pillar = CellType.Pillar; /*switch(Roll(4)){ //this part should be done later. Until then, they should remain pillars. case 1: case 2: pillar = CellType.Pillar; break; case 3: pillar = CellType.Statue; break; case 4: pillar = CellType.OtherRoomFeature; break; }*/ switch(layouts.Random()){ case PillarArrangement.Single: map[(start_r + end_r)/2,(start_c + end_c)/2] = pillar; break; case PillarArrangement.Row: { bool vertical; if(width % 2 == 1 && height % 2 == 0){ vertical = true; } else{ if(height % 2 == 1 && width % 2 == 0){ vertical = false; } else{ vertical = CoinFlip(); } } if(vertical){ if(height % 2 == 1){ for(int i=start_r+1;i<=end_r-1;i+=2){ map[i,(start_c + end_c)/2] = pillar; } } else{ int offset = 0; if(height % 4 == 0){ offset = Roll(2) - 1; } for(int i=start_r+1+offset;i<(start_r + end_r)/2;i+=2){ map[i,(start_c + end_c)/2] = pillar; } for(int i=end_r-1-offset;i>(start_r + end_r)/2+1;i-=2){ map[i,(start_c + end_c)/2] = pillar; } } } else{ if(width % 2 == 1){ for(int i=start_c+1;i<=end_c-1;i+=2){ map[(start_r + end_r)/2,i] = pillar; } } else{ int offset = 0; if(width % 4 == 0){ offset = Roll(2) - 1; } for(int i=start_c+1+offset;i<(start_c + end_c)/2;i+=2){ map[(start_r + end_r)/2,i] = pillar; } for(int i=end_c-1-offset;i>(start_c + end_c)/2+1;i-=2){ map[(start_r + end_r)/2,i] = pillar; } } } break; } case PillarArrangement.Corners: { int v_offset = 0; int h_offset = 0; if(height % 4 == 0){ v_offset = Roll(2) - 1; } if(width % 4 == 0){ h_offset = Roll(2) - 1; } map[start_r + 1 + v_offset,start_c + 1 + h_offset] = pillar; map[start_r + 1 + v_offset,end_c - 1 - h_offset] = pillar; map[end_r - 1 - v_offset,start_c + 1 + h_offset] = pillar; map[end_r - 1 - v_offset,end_c - 1 - h_offset] = pillar; break; } case PillarArrangement.Full: { int v_offset = 0; int h_offset = 0; if(height % 4 == 0){ v_offset = Roll(2) - 1; } if(width % 4 == 0){ h_offset = Roll(2) - 1; } int half_r = (start_r + end_r)/2; int half_c = (start_c + end_c)/2; int half_r_offset = (start_r + end_r + 1)/2; int half_c_offset = (start_c + end_c + 1)/2; for(int i=start_r+1+v_offset;i<half_r;i+=2){ for(int j=start_c+1+h_offset;j<half_c;j+=2){ map[i,j] = pillar; } } for(int i=start_r+1+v_offset;i<half_r;i+=2){ for(int j=end_c-1-h_offset;j>half_c_offset;j-=2){ map[i,j] = pillar; } } for(int i=end_r-1-v_offset;i>half_r_offset;i-=2){ for(int j=start_c+1+h_offset;j<half_c;j+=2){ map[i,j] = pillar; } } for(int i=end_r-1-v_offset;i>half_r_offset;i-=2){ for(int j=end_c-1-h_offset;j>half_c_offset;j-=2){ map[i,j] = pillar; } } if((width+1) % 4 == 0){ if(height % 2 == 1){ for(int i=start_r+1;i<=end_r-1;i+=2){ map[i,half_c] = pillar; } } else{ int offset = 0; if(height % 4 == 0){ offset = Roll(2) - 1; } for(int i=start_r+1+offset;i<half_r;i+=2){ map[i,half_c] = pillar; } for(int i=end_r-1-offset;i>half_r_offset;i-=2){ map[i,half_c] = pillar; } } } if((height+1) % 4 == 0){ if(width % 2 == 1){ for(int i=start_c+1;i<=end_c-1;i+=2){ map[half_r,i] = pillar; } } else{ int offset = 0; if(width % 4 == 0){ offset = Roll(2) - 1; } for(int i=start_c+1+offset;i<half_c;i+=2){ map[half_r,i] = pillar; } for(int i=end_c-1-offset;i>half_c_offset;i-=2){ map[half_r,i] = pillar; } } } break; } case PillarArrangement.StatueCorners: map[start_r,start_c] = CellType.Statue; map[start_r,end_c] = CellType.Statue; map[end_r,start_c] = CellType.Statue; map[end_r,end_c] = CellType.Statue; break; case PillarArrangement.StatueEdges: { map[start_r,start_c] = CellType.Statue; map[start_r,end_c] = CellType.Statue; map[end_r,start_c] = CellType.Statue; map[end_r,end_c] = CellType.Statue; if(width % 2 == 1 && width > 3){ int half_c = (start_c + end_c)/2; int corridors = new pos(start_r,half_c).CardinalAdjacentPositions().Where(x => BoundsCheck(x) && map[x].IsCorridorType()).Count; if(corridors == 0){ map[start_r,half_c] = CellType.Statue; } corridors = new pos(end_r,half_c).CardinalAdjacentPositions().Where(x => BoundsCheck(x) && map[x].IsCorridorType()).Count; if(corridors == 0){ map[end_r,half_c] = CellType.Statue; } } if(height % 2 == 1 && height > 3){ int half_r = (start_r + end_r)/2; int corridors = new pos(half_r,start_c).CardinalAdjacentPositions().Where(x => BoundsCheck(x) && map[x].IsCorridorType()).Count; if(corridors == 0){ map[half_r,start_c] = CellType.Statue; } corridors = new pos(half_r,end_c).CardinalAdjacentPositions().Where(x => BoundsCheck(x) && map[x].IsCorridorType()).Count; if(corridors == 0){ map[half_r,end_c] = CellType.Statue; } } break; } default: break; } } } } return true; }); }
public void Execute() { if(!dead){ switch(type){ case EventType.MOVE: { Actor temp = target as Actor; temp.Act(); break; } case EventType.REMOVE_ATTR: { Actor temp = target as Actor; if(attr == AttrType.FLYING){ temp.attrs[AttrType.DESCENDING] = 2; if(temp == player){ B.Add("You start to descend as your flight wears off. "); B.Print(true); } break; } if(attr == AttrType.SHINING){ int old_rad = temp.LightRadius(); temp.attrs[attr] -= value; if(old_rad != temp.LightRadius() && !temp.HasAttr(AttrType.BURROWING)){ temp.UpdateRadius(old_rad,temp.LightRadius()); } break; } if(temp.type == ActorType.BERSERKER && attr == AttrType.COOLDOWN_2){ temp.attrs[attr] = 0; //this hack can probably be removed } else{ temp.attrs[attr] -= value; } if(attr == AttrType.BURNING && temp.LightRadius() == 0 && !temp.HasAttr(AttrType.BURROWING)){ temp.UpdateRadius(1,0); } if(attr == AttrType.TELEPORTING){ temp.attrs[attr] = 0; } if(attr == AttrType.CONVICTION){ if(temp.HasAttr(AttrType.IN_COMBAT)){ temp.attrs[AttrType.CONVICTION] += value; //whoops, undo that } else{ temp.attrs[AttrType.BONUS_SPIRIT] -= value; //otherwise, set things to normal temp.attrs[AttrType.BONUS_COMBAT] -= (value+1) / 2; if(temp.attrs[AttrType.KILLSTREAK] >= 2){ B.Add("You wipe off your weapon. "); } temp.attrs[AttrType.KILLSTREAK] = 0; } } if(attr == AttrType.COOLDOWN_1 && temp.type == ActorType.BERSERKER){ B.Add(temp.Your() + " rage diminishes. ",temp); B.Add(temp.the_name + " dies. ",temp); temp.Kill(); } break; } case EventType.REMOVE_GAS: { List<Tile> removed = new List<Tile>(); foreach(Tile t in area){ if(t.Is(feature)){ if(R.PercentChance(value)){ t.RemoveFeature(feature); removed.Add(t); } } else{ removed.Add(t); } } foreach(Tile t in removed){ area.Remove(t); } if(area.Count > 0){ Event.RemoveGas(area,100,feature,value); } break; } case EventType.CHECK_FOR_HIDDEN: { List<Tile> removed = new List<Tile>(); foreach(Tile t in area){ if(player.CanSee(t)){ int exponent = player.DistanceFrom(t) + 1; if(player.magic_trinkets.Contains(MagicTrinketType.RING_OF_KEEN_SIGHT)){ --exponent; } if(!t.IsLit()){ if(!player.HasAttr(AttrType.SHADOWSIGHT)){ ++exponent; } } if(exponent > 8){ exponent = 8; //because 1 in 256 is enough. } int difficulty = 1; for(int i=exponent;i>0;--i){ difficulty = difficulty * 2; } if(R.Roll(difficulty) == difficulty){ if(t.IsTrap() || t.Is(TileType.FIRE_GEYSER) || t.Is(TileType.FOG_VENT) || t.Is(TileType.POISON_GAS_VENT)){ t.name = Tile.Prototype(t.type).name; t.a_name = Tile.Prototype(t.type).a_name; t.the_name = Tile.Prototype(t.type).the_name; t.symbol = Tile.Prototype(t.type).symbol; t.color = Tile.Prototype(t.type).color; B.Add("You notice " + t.AName(true) + ". "); } else{ if(t.type == TileType.HIDDEN_DOOR){ t.Toggle(null); B.Add("You notice a hidden door. "); } } removed.Add(t); } } } foreach(Tile t in removed){ area.Remove(t); } if(area.Count > 0){ Q.Add(new Event(area,100,EventType.CHECK_FOR_HIDDEN)); } break; } case EventType.RELATIVELY_SAFE: { if(M.AllActors().Count == 1 && !Q.Contains(EventType.POLTERGEIST) && !Q.Contains(EventType.REGENERATING_FROM_DEATH) && !Q.Contains(EventType.MIMIC) && !Q.Contains(EventType.MARBLE_HORROR)){ //B.Add("The dungeon is still and silent. "); B.Add("The dungeon is utterly silent for a moment. "); B.PrintAll(); } else{ Q.Add(new Event((R.Roll(20)+30)*100,EventType.RELATIVELY_SAFE)); } break; } case EventType.POLTERGEIST: { if(target != null && target is Actor){ //target can either be a stolen item, or the currently manifested poltergeist. Q.Add(new Event(target,area,(R.Roll(8)+6)*100,EventType.POLTERGEIST,AttrType.NO_ATTR,0,"")); break; //if it's manifested, the event does nothing for now. } if(area.Any(t => t.actor() == player)){ bool manifested = false; if(value == 0){ B.Add("You feel like you're being watched. "); } else{ if(target != null){ //if it has a stolen item Tile tile = null; tile = area.Where(t => t.actor() == null && t.DistanceFrom(player) >= 2 && t.HasLOE(player) && t.FirstActorInLine(player) == player).RandomOrDefault(); if(tile != null){ Actor temporary = new Actor(ActorType.POLTERGEIST,"something",'G',Color.DarkGreen,1,1,0,0); temporary.a_name = "something"; temporary.the_name = "something"; temporary.p = tile.p; temporary.inv = new List<Item>(); temporary.inv.Add(target as Item); Item item = temporary.inv[0]; if(item.NameOfItemType() == "orb"){ temporary.inv[0].Use(temporary,temporary.GetBestExtendedLineOfEffect(player)); } else{ B.Add("Something throws " + item.AName() + ". ",temporary); B.DisplayNow(); Screen.AnimateProjectile(tile.GetBestExtendedLineOfEffect(player).ToFirstSolidTileOrActor(),new colorchar(item.color,item.symbol)); player.tile().GetItem(item); B.Add(item.TheName() + " hits you. "); player.TakeDamage(DamageType.NORMAL,DamageClass.PHYSICAL,R.Roll(6),temporary,"a flying " + item.Name()); } target = null; } else{ Q.Add(new Event(target,area,100,EventType.POLTERGEIST,AttrType.NO_ATTR,value,"")); return; //try again next turn } } else{ if(value >= 2 && area.Any(t => t.DistanceFrom(player) == 1 && t.passable && t.actor() == null)){ Tile tile = area.Where(t => t.DistanceFrom(player) == 1 && t.passable && t.actor() == null).Random(); B.DisplayNow(); for(int i=4;i>0;--i){ Screen.AnimateStorm(tile.p,i,2,1,'G',Color.DarkGreen); } Actor a = Actor.Create(ActorType.POLTERGEIST,tile.row,tile.col,TiebreakerAssignment.UseCurrent); Q.KillEvents(a,EventType.MOVE); a.Q0(); a.player_visibility_duration = -1; B.Add("A poltergeist manifests in front of you! "); Q.Add(new Event(a,area,(R.Roll(8)+6)*100,EventType.POLTERGEIST,AttrType.NO_ATTR,0,"")); manifested = true; } else{ if(player.tile().type == TileType.DOOR_O){ B.Add("The door slams closed on you! "); player.TakeDamage(DamageType.NORMAL,DamageClass.PHYSICAL,R.Roll(6),null,"a slamming door"); } else{ Tile tile = null; //check for items to throw... tile = area.Where(t => t.inv != null && t.actor() == null && t.DistanceFrom(player) >= 2 && t.HasLOE(player) && t.FirstActorInLine(player) == player).RandomOrDefault(); if(tile != null){ Actor temporary = new Actor(ActorType.POLTERGEIST,"something",'G',Color.DarkGreen,1,1,0,0); temporary.a_name = "something"; temporary.the_name = "something"; temporary.p = tile.p; temporary.inv = new List<Item>(); if(tile.inv.quantity <= 1){ temporary.inv.Add(tile.inv); tile.inv = null; } else{ temporary.inv.Add(new Item(tile.inv,-1,-1)); tile.inv.quantity--; } M.Draw(); Item item = temporary.inv[0]; if(item.NameOfItemType() == "orb"){ temporary.inv[0].Use(temporary,temporary.GetBestExtendedLineOfEffect(player)); } else{ B.Add("Something throws " + item.TheName() + ". ",temporary); B.DisplayNow(); Screen.AnimateProjectile(tile.GetBestExtendedLineOfEffect(player).ToFirstSolidTileOrActor(),new colorchar(item.color,item.symbol)); player.tile().GetItem(item); B.Add(item.TheName() + " hits you. "); player.TakeDamage(DamageType.NORMAL,DamageClass.PHYSICAL,R.Roll(6),temporary,"a flying " + item.Name()); } } else{ if(area.Any(t => t.type == TileType.DOOR_O || t.type == TileType.DOOR_C)){ Tile door = area.Where(t=>t.type == TileType.DOOR_O || t.type == TileType.DOOR_C).Random(); if(door.type == TileType.DOOR_C){ if(player.CanSee(door)){ B.Add("The door flies open! ",door); } else{ if(door.seen || player.DistanceFrom(door) <= 12){ B.Add("You hear a door slamming. "); } } door.Toggle(null); } else{ if(door.actor() == null){ if(player.CanSee(door)){ B.Add("The door slams closed! ",door); } else{ if(door.seen || player.DistanceFrom(door) <= 12){ B.Add("You hear a door slamming. "); } } door.Toggle(null); } else{ if(player.CanSee(door)){ B.Add("The door slams closed on " + door.actor().TheName(true) + "! ",door); } else{ if(player.DistanceFrom(door) <= 12){ B.Add("You hear a door slamming and a grunt of pain. "); } } door.actor().TakeDamage(DamageType.NORMAL,DamageClass.PHYSICAL,R.Roll(6),null,"a slamming door"); } } } else{ B.Add("You hear mocking laughter from nearby. "); } } } } } } if(!manifested){ Q.Add(new Event(target,area,(R.Roll(8)+6)*100,EventType.POLTERGEIST,AttrType.NO_ATTR,value+1,"")); } } else{ Q.Add(new Event(target,area,(R.Roll(8)+6)*100,EventType.POLTERGEIST,AttrType.NO_ATTR,0,"")); } break; } case EventType.MIMIC: { Item item = target as Item; if(area[0].inv != item){ //it could have been picked up by the player or moved in another way foreach(Tile t in M.AllTiles()){ //if it was moved, make the correction to the event's area. if(t.inv == item){ area = new List<Tile>{t}; break; } } } if(area[0].inv == item){ bool attacked = false; if(player.DistanceFrom(area[0]) == 1 && area[0].actor() == null){ if(player.TotalSkill(SkillType.STEALTH) * 5 < R.Roll(1,100)){ B.Add(item.TheName(true) + " suddenly grows tentacles! "); attacked = true; area[0].inv = null; Actor a = Actor.Create(ActorType.MIMIC,area[0].row,area[0].col,TiebreakerAssignment.UseCurrent); Q.KillEvents(a,EventType.MOVE); a.Q0(); a.player_visibility_duration = -1; a.symbol = item.symbol; a.color = item.color; } } if(!attacked){ Q.Add(new Event(target,area,100,EventType.MIMIC,AttrType.NO_ATTR,0,"")); } } else{ //if the item is missing, we assume that the player just picked it up List<Tile> open = new List<Tile>(); foreach(Tile t in player.TilesAtDistance(1)){ if(t.passable && t.actor() == null){ open.Add(t); } } if(open.Count > 0){ Tile t = open.Random(); B.Add(item.TheName() + " suddenly grows tentacles! "); Actor a = Actor.Create(ActorType.MIMIC,t.row,t.col,TiebreakerAssignment.UseCurrent); Q.KillEvents(a,EventType.MOVE); a.Q0(); a.player_visibility_duration = -1; a.symbol = item.symbol; a.color = item.color; player.inv.Remove(item); } else{ B.Add("Your pack feels lighter. "); player.inv.Remove(item); } } break; } case EventType.GRENADE: { Tile t = target as Tile; if(t.Is(FeatureType.GRENADE)){ t.features.Remove(FeatureType.GRENADE); B.Add("The grenade explodes! ",t); if(t.seen){ Screen.WriteMapChar(t.row,t.col,M.VisibleColorChar(t.row,t.col)); } B.DisplayNow(); t.ApplyExplosion(1,"an exploding grenade"); /*List<pos> cells = new List<pos>(); foreach(Tile tile in t.TilesWithinDistance(1)){ if(tile.passable && tile.seen){ //animation LOS check here cells.Add(tile.p); } } Screen.AnimateMapCells(cells,new colorchar('*',Color.RandomExplosion)); Actor a = t.actor(); if(a != null){ a.attrs[AttrType.TURN_INTO_CORPSE] = 1; } foreach(Actor a2 in t.ActorsWithinDistance(1)){ a2.TakeDamage(DamageType.NORMAL,DamageClass.PHYSICAL,R.Roll(3,6),null,"an exploding grenade"); } if(a != null){ int dir = Global.RandomDirection(); if(a.curhp > 0 || !a.HasAttr(AttrType.NO_CORPSE_KNOCKBACK)){ t.TileInDirection(dir).KnockObjectBack(a,1); } a.CorpseCleanup(); } t.MakeNoise(8);*/ } break; } case EventType.BLAST_FUNGUS: { Item i = target as Item; i.other_data--; if(i.other_data == 0){ Tile t = null; if(M.tile.BoundsCheck(i.row,i.col) && M.tile[i.p].inv == i){ t = M.tile[i.p]; t.inv = null; } else{ foreach(Actor a in M.AllActors()){ if(a.inv.Contains(i)){ a.inv.Remove(i); t = a.tile(); break; } } } if(t != null){ B.Add("The blast fungus explodes! ",t); if(t.seen){ Screen.WriteMapChar(t.row,t.col,M.VisibleColorChar(t.row,t.col)); } B.DisplayNow(); t.ApplyExplosion(3,"an exploding blast fungus"); } } else{ Tile t = null; if(M.tile.BoundsCheck(i.row,i.col) && M.tile[i.p].inv == i){ t = M.tile[i.p]; } else{ foreach(Actor a in M.AllActors()){ if(a.inv.Contains(i)){ t = a.tile(); break; } } } if(t != null && t.seen){ Screen.AnimateMapCell(t.row,t.col,new colorchar(i.other_data.ToString()[0],Color.Red),100); } Q.Add(new Event(i,100,EventType.BLAST_FUNGUS)); } break; } case EventType.STALAGMITE: { if(value > 1){ int stalagmites = 0; //number removed int number_left = 0; List<Tile> crumbled = new List<Tile>(); foreach(Tile tile in area){ if(tile.type == TileType.STALAGMITE){ if(R.OneIn(value)){ crumbled.Add(tile); tile.Toggle(null); ++stalagmites; } else{ ++number_left; } } } if(stalagmites > 0){ if(stalagmites > 1){ B.Add("The stalagmites crumble. ",crumbled.ToArray()); } else{ B.Add("The stalagmite crumbles. ",crumbled.ToArray()); } } if(number_left > 0){ Q.Add(new Event(area,100,EventType.STALAGMITE,value)); } } else{ int stalagmites = 0; foreach(Tile tile in area){ if(tile.type == TileType.STALAGMITE){ stalagmites++; } } if(stalagmites > 0){ if(stalagmites > 1){ B.Add("The stalagmites crumble. ",area.ToArray()); } else{ B.Add("The stalagmite crumbles. ",area.ToArray()); } foreach(Tile tile in area){ if(tile.type == TileType.STALAGMITE){ tile.Toggle(null); } } } } break; } case EventType.FIRE_GEYSER: { int frequency = value / 10; //9-39 int variance = value % 10; //0-9 int variance_amount = (frequency * variance) / 10; int number_of_values = variance_amount*2 + 1; int minimum_value = frequency - variance_amount; if(minimum_value < 5){ int diff = 5 - minimum_value; number_of_values -= diff; minimum_value = 5; } int delay = ((minimum_value - 1) + R.Roll(number_of_values)) * 100; Q.Add(new Event(target,delay+200,EventType.FIRE_GEYSER,value)); Q.Add(new Event(target,delay,EventType.FIRE_GEYSER_ERUPTION,2)); break; } case EventType.FIRE_GEYSER_ERUPTION: { foreach(Tile t in target.TilesWithinDistance(2)){ t.RemoveFeature(FeatureType.FOG); } //int old_radius = target.light_radius; //target.UpdateRadius(old_radius,2,true); B.Add(target.the_name + " spouts flames! ",target); if(target.actor() != null){ target.actor().ApplyBurning(); } for(int i=0;i<4;++i){ Tile t = target.TilesWithinDistance(2).Where(x=>target.HasLOE(x)).RandomOrDefault(); if(t != null){ if(t.passable){ t.AddFeature(FeatureType.FIRE); } else{ t.ApplyEffect(DamageType.FIRE); } } } //target.UpdateRadius(2,old_radius,true); if(value > 0){ Q.Add(new Event(target,100,EventType.FIRE_GEYSER_ERUPTION,value - 1)); } break; } case EventType.FOG_VENT: { Tile current = target as Tile; if(!current.Is(FeatureType.FOG)){ current.AddFeature(FeatureType.FOG); List<Tile> new_area = new List<Tile>{current}; Q.RemoveTilesFromEventAreas(new_area,EventType.REMOVE_GAS); Event.RemoveGas(new_area,600,FeatureType.FOG,25); //Q.Add(new Event(new_area,600,EventType.FOG,25)); } else{ for(int tries=0;tries<50;++tries){ List<Tile> open = new List<Tile>(); foreach(Tile t in current.TilesAtDistance(1)){ //perhaps the rework could involve refreshing the duration of nearby tiles - if enough are refreshed, then no new tiles need to be added if(t.passable){ open.Add(t); if(!t.Is(FeatureType.FOG)){ open.Add(t); //3x as likely if it can expand there open.Add(t); } } } if(open.Count > 0){ Tile possible = open.Random(); if(!possible.Is(FeatureType.FOG)){ possible.AddFeature(FeatureType.FOG); List<Tile> new_area = new List<Tile>{possible}; Q.RemoveTilesFromEventAreas(new_area,EventType.REMOVE_GAS); Event.RemoveGas(new_area,600,FeatureType.FOG,25); break; } else{ current = possible; } } else{ break; } } } Q.Add(new Event(target,100,EventType.FOG_VENT)); break; } case EventType.POISON_GAS_VENT: { Tile current = target as Tile; if(R.OneIn(7)){ int num = R.Roll(5) + 2; List<Tile> new_area = new List<Tile>(); for(int i=0;i<num;++i){ if(!current.Is(FeatureType.POISON_GAS)){ current.AddFeature(FeatureType.POISON_GAS); new_area.Add(current); } else{ for(int tries=0;tries<50;++tries){ List<Tile> open = new List<Tile>(); foreach(Tile t in current.TilesAtDistance(1)){ if(t.passable){ open.Add(t); } } if(open.Count > 0){ Tile possible = open.Random(); if(!possible.Is(FeatureType.POISON_GAS)){ possible.AddFeature(FeatureType.POISON_GAS); new_area.Add(possible); break; } else{ current = possible; } } else{ break; } } } } if(new_area.Count > 0){ B.Add("Toxic vapors pour from " + target.the_name + "! ",target); Event.RemoveGas(new_area,200,FeatureType.POISON_GAS,18); } } Q.Add(new Event(target,100,EventType.POISON_GAS_VENT)); break; } case EventType.STONE_SLAB: { Tile t = target as Tile; if(t.type == TileType.STONE_SLAB && (t.IsLitFromAnywhere(true) || area.Any(x=>x.actor()!=null))){ bool vis = player.CanSee(t); t.Toggle(null); //t.Toggle(null,TileType.FLOOR); //t.symbol = '-'; //t.revealed_by_light = true; if(!vis && player.CanSee(t)){ vis = true; } if(vis){ B.Add("The stone slab rises with a grinding sound. "); } else{ if(player.DistanceFrom(t) <= 6){ B.Add("You hear a grinding sound. "); } } } else{ if(t.type == TileType.STONE_SLAB_OPEN && !t.IsLitFromAnywhere(true) && t.actor() == null && !area.Any(x=>x.actor()!=null)){ bool vis = player.CanSee(t); //t.Toggle(null,TileType.STONE_SLAB); t.Toggle(null); if(!vis && player.CanSee(t)){ vis = true; } if(vis){ B.Add("The stone slab descends with a grinding sound. "); } else{ if(player.DistanceFrom(t) <= 6){ B.Add("You hear a grinding sound. "); } } } } Q.Add(new Event(target,area,100,EventType.STONE_SLAB)); break; } case EventType.MARBLE_HORROR: { Tile t = target as Tile; if(t.type == TileType.STATUE){ if(value == 1 && player.CanSee(t) && !t.IsLit() && t.actor() == null){ //if target was visible last turn & this turn, and it's currently in darkness... t.TransformTo(TileType.FLOOR); Actor a = Actor.Create(ActorType.MARBLE_HORROR,t.row,t.col,TiebreakerAssignment.AtEnd); //todo: not sure - should this get a placeholder like poltergeist and mimic? foreach(Event e in Q.list){ if(e.target == a && e.type == EventType.MOVE){ e.dead = true; break; } } a.Q0(); switch(R.Roll(2)){ case 1: B.Add("You think that statue might have just moved... "); B.Print(true); break; case 2: B.Add("The statue turns its head to face you. "); B.Print(true); break; } } else{ if(player.CanSee(t)){ Q.Add(new Event(target,100,EventType.MARBLE_HORROR,1)); } else{ Q.Add(new Event(target,100,EventType.MARBLE_HORROR,0)); } } } break; } case EventType.REGENERATING_FROM_DEATH: { int health = value; int permanent_damage = secondary_value; if(target.tile().Is(FeatureType.TROLL_CORPSE)){ //otherwise, assume it was destroyed by fire int maxhp = Actor.Prototype(ActorType.TROLL).maxhp; int recovered = Actor.Prototype(ActorType.TROLL).attrs[AttrType.REGENERATING]; if(health + recovered > maxhp - permanent_damage){ recovered = (maxhp - permanent_damage) - health; } health += recovered; if(permanent_damage >= maxhp){ break; } if(health > 0 && target.actor() == null){ Actor a = Actor.Create(ActorType.TROLL,target.row,target.col,TiebreakerAssignment.UseCurrent); a.curhp = health; a.attrs[AttrType.PERMANENT_DAMAGE] = permanent_damage; a.attrs[AttrType.NO_ITEM]++; a.attrs[AttrType.DANGER_SENSED]++; B.Add("The troll stands up! ",target); a.player_visibility_duration = -1; if(target.tile().type == TileType.DOOR_C){ target.tile().Toggle(a); } target.tile().features.Remove(FeatureType.TROLL_CORPSE); a.attrs[AttrType.WANDERING]++; } else{ int roll = R.Roll(20); if(health == -1){ roll = 1; } if(health == 0){ roll = 3; } switch(roll){ case 1: case 2: B.Add("The troll's corpse twitches. ",target); break; case 3: case 4: B.Add("You hear sounds coming from the troll's corpse. ",target); break; case 5: B.Add("The troll on the floor regenerates. ",target); break; default: break; } Event e = new Event(target,100,EventType.REGENERATING_FROM_DEATH); e.value = health; e.secondary_value = permanent_damage; Q.Add(e); } } if(target.tile().Is(FeatureType.TROLL_BLOODWITCH_CORPSE)){ //otherwise, assume it was destroyed by fire int maxhp = Actor.Prototype(ActorType.TROLL_BLOODWITCH).maxhp; int recovered = Actor.Prototype(ActorType.TROLL_BLOODWITCH).attrs[AttrType.REGENERATING]; if(health + recovered > maxhp - permanent_damage){ recovered = (maxhp - permanent_damage) - health; } health += recovered; if(permanent_damage >= maxhp){ break; } if(recovered > 0){ List<pos> cells = new List<pos>(); List<colorchar> cch = new List<colorchar>(); foreach(pos p2 in target.PositionsWithinDistance(4)){ if(target.HasLOE(M.tile[p2]) && player.CanSee(M.tile[p2])){ cells.Add(p2); colorchar ch = M.VisibleColorChar(p2.row,p2.col); ch.color = Color.Red; cch.Add(ch); } } if(cells.Count > 0){ M.Draw(); Screen.AnimateMapCells(cells,cch,40); } foreach(Actor a in target.ActorsWithinDistance(4)){ if(target.HasLOE(a)){ if(a == player){ B.Add("Ow! "); } a.TakeDamage(DamageType.NORMAL,DamageClass.MAGICAL,recovered,null,"trollish blood magic"); } } } if(health > 0 && target.actor() == null){ Actor a = Actor.Create(ActorType.TROLL_BLOODWITCH,target.row,target.col,TiebreakerAssignment.UseCurrent); a.curhp = health; a.attrs[AttrType.PERMANENT_DAMAGE] = permanent_damage; a.attrs[AttrType.NO_ITEM]++; a.attrs[AttrType.DANGER_SENSED]++; B.Add("The troll bloodwitch rises! ",target); a.player_visibility_duration = -1; if(attr == AttrType.COOLDOWN_1){ a.attrs[AttrType.COOLDOWN_1]++; } if(target.tile().type == TileType.DOOR_C){ target.tile().Toggle(a); } target.tile().features.Remove(FeatureType.TROLL_BLOODWITCH_CORPSE); a.attrs[AttrType.WANDERING]++; } else{ int roll = R.Roll(20); if(health == -1){ roll = 1; } if(health == 0){ roll = 3; } switch(roll){ case 1: case 2: B.Add("The bloodwitch's corpse twitches. ",target); break; case 3: case 4: B.Add("You feel a pulse like a heartbeat coming from the bloodwitch. ",target); break; case 5: B.Add("The troll bloodwitch on the floor regenerates. ",target); break; default: break; } Event e = new Event(target,100,EventType.REGENERATING_FROM_DEATH); e.value = health; e.secondary_value = permanent_damage; Q.Add(e); } } break; } case EventType.REASSEMBLING: { Tile t = target as Tile; if(t.Is(FeatureType.BONES)){ if(t.actor() == null){ Actor a = Actor.Create(ActorType.SKELETON,target.row,target.col,TiebreakerAssignment.UseCurrent); B.Add("The skeleton reassembles itself. ",target); a.player_visibility_duration = -1; if(target.tile().type == TileType.DOOR_C){ target.tile().Toggle(a); } target.tile().features.Remove(FeatureType.BONES); if(R.OneIn(3)){ a.attrs[AttrType.WANDERING]++; } } else{ Q.Add(new Event(target,100,EventType.REASSEMBLING)); } } break; } case EventType.SHIELDING: { List<pos> cells = new List<pos>(); List<colorchar> symbols = new List<colorchar>(); int animation_delay = 75; foreach(Tile tile in area){ colorchar cch = tile.visual; if(tile.actor() != null){ if(!tile.actor().HasAttr(AttrType.SHIELDED)){ tile.actor().attrs[AttrType.SHIELDED] = 1; B.Add(tile.actor().YouAre() + " shielded. ",tile.actor()); } if(player.CanSee(tile.actor())){ animation_delay = 150; cch = tile.actor().visual; } } cch.bgcolor = Color.Blue; if(Global.LINUX && !Screen.GLMode){ cch.bgcolor = Color.DarkBlue; } if(cch.color == cch.bgcolor){ cch.color = Color.Black; } if(cch.c == '.'){ cch.c = '+'; } symbols.Add(cch); cells.Add(tile.p); } M.Draw(); Screen.AnimateMapCells(cells,symbols,animation_delay); --value; if(value > 0){ Q.Add(new Event(area,100,EventType.SHIELDING,value)); } break; } case EventType.FINAL_LEVEL_SPAWN_CULTISTS: { int num_cultists = M.AllActors().Where(x=>x.Is(ActorType.FINAL_LEVEL_CULTIST)).Count; if(num_cultists < 5){ Actor a = M.SpawnMob(ActorType.CULTIST); if(a != null){ List<Actor> group = null; if(a.group != null){ group = new List<Actor>(a.group); a.group.Clear(); } else{ group = new List<Actor>{a}; } List<int> valid_circles = new List<int>(); for(int i=0;i<5;++i){ if(M.FinalLevelSummoningCircle(i).PositionsWithinDistance(2,M.tile).Any(x=>M.tile[x].Is(TileType.DEMONIC_IDOL))){ valid_circles.Add(i); } } foreach(Actor a2 in group){ int i = valid_circles.RemoveLast(); pos circle = M.FinalLevelSummoningCircle(i); a2.FindPath(circle.row,circle.col); a2.attrs[AttrType.COOLDOWN_2] = i; a2.type = ActorType.FINAL_LEVEL_CULTIST; a2.group = null; if(!R.OneIn(20)){ a2.attrs[AttrType.NO_ITEM] = 1; } } } } Q.Add(new Event(R.Between(5,8)*100,EventType.FINAL_LEVEL_SPAWN_CULTISTS)); break; } /*case EventType.BOSS_SIGN: { string s = ""; switch(R.Roll(8)){ case 1: s = "You see scratch marks on the walls and floor. "; break; case 2: s = "There are deep gouges in the floor here. "; break; case 3: s = "The floor here is scorched and blackened. "; break; case 4: s = "You notice bones of an unknown sort on the floor. "; break; case 5: s = "You hear a distant roar. "; break; case 6: s = "You smell smoke. "; break; case 7: s = "You spot a large reddish scale on the floor. "; break; case 8: s = "A small tremor shakes the area. "; break; default: s = "Debug message. "; break; } if(!player.HasAttr(AttrType.RESTING)){ B.AddIfEmpty(s); } Q.Add(new Event((R.Roll(20)+35)*100,EventType.BOSS_SIGN)); break; } case EventType.BOSS_ARRIVE: { bool spawned = false; Actor a = null; if(M.AllActors().Count == 1 && !Q.Contains(EventType.POLTERGEIST)){ List<Tile> trolls = new List<Tile>(); for(LinkedListNode<Event> current = Q.list.First;current!=null;current = current.Next){ if(current.Value.type == EventType.REGENERATING_FROM_DEATH){ trolls.Add((current.Value.target) as Tile); } } foreach(Tile troll in trolls){ if(troll.Is(FeatureType.TROLL_CORPSE)){ B.Add("The troll corpse burns to ashes! ",troll); troll.features.Remove(FeatureType.TROLL_CORPSE); } else{ if(troll.Is(FeatureType.TROLL_BLOODWITCH_CORPSE)){ B.Add("The troll bloodwitch corpse burns to ashes! ",troll); troll.features.Remove(FeatureType.TROLL_BLOODWITCH_CORPSE); } } } Q.KillEvents(null,EventType.REGENERATING_FROM_DEATH); List<Tile> goodtiles = M.AllTiles(); List<Tile> removed = new List<Tile>(); foreach(Tile t in goodtiles){ if(!t.passable || t.Is(TileType.CHASM) || player.CanSee(t)){ removed.Add(t); } } foreach(Tile t in removed){ goodtiles.Remove(t); } if(goodtiles.Count > 0){ B.Add("You hear a loud crash and a nearby roar! "); Tile t = goodtiles[R.Roll(goodtiles.Count)-1]; a = Actor.Create(ActorType.FIRE_DRAKE,t.row,t.col,true,false); spawned = true; } else{ if(M.AllTiles().Any(t=>t.passable && !t.Is(TileType.CHASM) && t.actor() == null)){ B.Add("You hear a loud crash and a nearby roar! "); Tile tile = M.AllTiles().Where(t=>t.passable && !t.Is(TileType.CHASM) && t.actor() == null).Random(); a = Actor.Create(ActorType.FIRE_DRAKE,tile.row,tile.col,true,false); spawned = true; } } } if(!spawned){ Q.Add(new Event(null,null,(R.Roll(20)+10)*100,EventType.BOSS_ARRIVE,attr,value,"")); } else{ if(value > 0){ a.curhp = value; } else{ //if there's no good value, this means that this is the first appearance. B.Add("The ground shakes as dust and rocks fall from the cavern ceiling. "); B.Add("This place is falling apart! "); List<Tile> floors = M.AllTiles().Where(t=>t.passable && t.type != TileType.CHASM && player.tile() != t); Tile tile = null; if(floors.Count > 0){ tile = floors.Random(); (tile as Tile).Toggle(null,TileType.CHASM); } Q.Add(new Event(tile,100,EventType.FLOOR_COLLAPSE)); Q.Add(new Event((R.Roll(20)+20)*100,EventType.CEILING_COLLAPSE)); } } break; } case EventType.FLOOR_COLLAPSE: { Tile current = target as Tile; int tries = 0; if(current != null){ for(tries=0;tries<50;++tries){ List<Tile> open = new List<Tile>(); foreach(Tile t in current.TilesAtDistance(1)){ if(t.passable || t.Is(TileType.RUBBLE)){ open.Add(t); } } if(open.Count > 0){ Tile possible = open.Random(); if(!possible.Is(TileType.CHASM)){ possible.Toggle(null,TileType.CHASM); List<Tile> open_neighbors = possible.TilesAtDistance(1).Where(t=>t.passable && t.type != TileType.CHASM); int num_neighbors = open_neighbors.Count; while(open_neighbors.Count > num_neighbors/2){ Tile neighbor = open_neighbors.RemoveRandom(); neighbor.Toggle(null,TileType.CHASM); } break; } else{ current = possible; } } else{ break; } } } if(tries == 50 || current == null){ List<Tile> floors = M.AllTiles().Where(t=>t.passable && t.type != TileType.CHASM && player.tile() != t); if(floors.Count > 0){ target = floors.Random(); (target as Tile).Toggle(null,TileType.CHASM); } } Q.Add(new Event(target,100,EventType.FLOOR_COLLAPSE)); break; } case EventType.CEILING_COLLAPSE: { B.Add("The ground shakes and debris falls from the ceiling! "); for(int i=1;i<Global.ROWS-1;++i){ for(int j=1;j<Global.COLS-1;++j){ Tile t = M.tile[i,j]; if(t.Is(TileType.WALL)){ int num_walls = t.TilesAtDistance(1).Where(x=>x.Is(TileType.WALL)).Count; if(num_walls < 8 && R.OneIn(20)){ if(R.CoinFlip()){ t.Toggle(null,TileType.FLOOR); foreach(Tile neighbor in t.TilesAtDistance(1)){ neighbor.solid_rock = false; } } else{ t.Toggle(null,TileType.RUBBLE); foreach(Tile neighbor in t.TilesAtDistance(1)){ neighbor.solid_rock = false; if(neighbor.type == TileType.FLOOR && R.OneIn(10)){ neighbor.Toggle(null,TileType.RUBBLE); } } } } } else{ int num_walls = t.TilesAtDistance(1).Where(x=>x.Is(TileType.WALL)).Count; if(num_walls == 0 && R.OneIn(100)){ if(R.OneIn(6)){ t.Toggle(null,TileType.RUBBLE); } foreach(Tile neighbor in t.TilesAtDistance(1)){ if(neighbor.type == TileType.FLOOR && R.OneIn(6)){ neighbor.Toggle(null,TileType.RUBBLE); } } } } } } Q.Add(new Event((R.Roll(20)+20)*100,EventType.CEILING_COLLAPSE)); break; }*/ case EventType.NORMAL_LIGHTING: { bool check_for_torch_dimming = false; if(M.wiz_lite){ B.Add("The supernatural brightness fades from the air. "); } if(M.wiz_dark){ B.Add("The supernatural darkness fades from the air. "); check_for_torch_dimming = true; } M.wiz_lite = false; M.wiz_dark = false; if(check_for_torch_dimming && player.HasAttr(AttrType.DIM_LIGHT)){ player.CalculateDimming(); } break; } case EventType.TELEPORTAL: { Tile t = target as Tile; if(t != null && t.Is(FeatureType.TELEPORTAL,FeatureType.STABLE_TELEPORTAL)){ if(t.Is(FeatureType.TELEPORTAL)){ value--; //unstable teleportals (from the item) degrade each turn } else{ if(value < 100){ value++; //stable ones repair themselves after use } } Actor a = t.actor(); Tile dest = null; if(a != null && !a.HasAttr(AttrType.JUST_TELEPORTED,AttrType.IMMOBILE)){ if(area != null){ dest = area.RandomOrDefault(); } else{ List<Tile> tiles = M.AllTiles().Where(x => x.passable && x.actor() == null && t.ApproximateEuclideanDistanceFromX10(x) >= 45); dest = tiles.RandomOrDefault(); } if(dest != null){ a.RefreshDuration(AttrType.JUST_TELEPORTED,101); value -= 25; bool visible = false; if(a == player){ B.Add("You disappear into the teleportal. "); } else{ if(player.CanSee(a)){ visible = true; B.Add(a.the_name + " disappears into the teleportal. ",t); } } a.Move(dest.row,dest.col); if(a != player && player.CanSee(a)){ if(visible){ B.Add(a.the_name + " reappears. ",a); } else{ B.Add(a.a_name + " suddenly appears! ",a); } } } } else{ if(a != null && a.HasAttr(AttrType.JUST_TELEPORTED)){ a.RefreshDuration(AttrType.JUST_TELEPORTED,101); } } if(t.inv != null && t.Is(FeatureType.TELEPORTAL)){ List<Tile> tiles = M.AllTiles().Where(x => x.passable && x.inv == null && t.ApproximateEuclideanDistanceFromX10(x) >= 45); dest = tiles.RandomOrDefault(); if(dest != null){ Item i = t.inv; bool visible = false; if(player.CanSee(t)){ visible = true; B.Add(i.TheName(true) + " disappears into the teleportal. ",t); } t.inv = null; dest.GetItem(i); if(player.CanSee(dest)){ if(visible){ B.Add(i.TheName(true) + " reappears. ",dest); } else{ B.Add(i.AName(true) + " suddenly appears! ",dest); } } } } if(value > 0){ Q.Add(new Event(target,area,100,EventType.TELEPORTAL,AttrType.NO_ATTR,value,"")); if(value < 25){ if(dest != null || R.OneIn(8)){ B.Add("The teleportal flickers. ",t,dest); } } } else{ if(t.Is(FeatureType.TELEPORTAL)){ t.RemoveFeature(FeatureType.TELEPORTAL); } if(t.Is(FeatureType.STABLE_TELEPORTAL)){ foreach(Tile t2 in area){ Event e2 = Q.FindTargetedEvent(t2,EventType.TELEPORTAL); if(e2 != null && t2.features.Contains(FeatureType.STABLE_TELEPORTAL)){ e2.area.Remove(t); if(e2.area.Count == 0){ t2.RemoveFeature(FeatureType.STABLE_TELEPORTAL); //t2.AddFeature(FeatureType.INACTIVE_TELEPORTAL); e2.dead = true; } } } t.RemoveFeature(FeatureType.STABLE_TELEPORTAL); } B.Add("The teleportal flickers and vanishes. ",t,dest); } } break; } case EventType.BREACH: { if(!R.OneIn(3)){ Tile t = area.WhereGreatest(x=>x.DistanceFrom(target)).RandomOrDefault(); if(t != null){ t.Toggle(null); if(t.actor() != null || t.inv != null){ foreach(Tile nearby in M.ReachableTilesByDistance(t.row,t.col,false)){ if(t.inv != null && nearby.inv == null){ nearby.GetItem(t.inv); t.inv = null; if(t.actor() == null){ break; } } if(t.actor() != null && nearby.actor() == null){ t.actor().Move(nearby.row,nearby.col); if(t.inv == null){ break; } } } if(t.actor() != null){ //if there wasn't an actual path to a passable tile, just move to the nearest for(int i=1;i<Math.Max(Global.ROWS,Global.COLS);++i){ List<Tile> tiles = t.TilesAtDistance(i).Where(x=>x.passable && x.actor() == null); bool done = false; while(tiles.Count > 0){ Tile dest = tiles.Random(); t.actor().Move(dest.row,dest.col); done = true; break; } if(done){ break; } } } if(t.inv != null){ for(int i=1;i<Math.Max(Global.ROWS,Global.COLS);++i){ List<Tile> tiles = t.TilesAtDistance(i).Where(x=>x.passable && x.inv == null); bool done = false; while(tiles.Count > 0){ Tile dest = tiles.Random(); dest.GetItem(t.inv); t.inv = null; done = true; break; } if(done){ break; } } } } if(t.features.Count > 0){ t.features.Clear(); } area.Remove(t); } } if(area.Count > 0){ Q.Add(new Event(target,area,100,EventType.BREACH)); } break; } case EventType.GRAVE_DIRT: { foreach(Tile t in area){ Actor a = t.actor(); if(a != null && a.type != ActorType.CORPSETOWER_BEHEMOTH && !a.HasAttr(AttrType.IMMOBILE,AttrType.JUST_GRABBED,AttrType.FROZEN,AttrType.FLYING) && R.OneIn(12)){ if(player.CanSee(a)){ B.Add("A dead hand reaches up and grabs " + a.the_name + "! ",t); } if(a == player){ B.Print(true); } if(a.HasAttr(AttrType.SLIMED,AttrType.OIL_COVERED,AttrType.BRUTISH_STRENGTH)){ if(player.CanSee(a)){ B.Add(a.You("slip") + " out of its grasp. ",t); } } else{ int duration = R.Roll(4) * 100; a.attrs[AttrType.IMMOBILE]++; Q.Add(new Event(a,duration,AttrType.IMMOBILE,"The dead hand releases " + a.TheName(true) + ". ",t)); //it'd be nice to check LOS here a.RefreshDuration(AttrType.JUST_GRABBED,duration + 100); } } } Q.Add(new Event(area,100,EventType.GRAVE_DIRT)); break; } case EventType.TOMBSTONE_GHOST: { if(area.Count > 0){ Tile t = area[0]; if(target == null && t.actor() == player){ foreach(Tile t2 in M.ReachableTilesByDistance(player.row,player.col,false)){ if(t2.passable && t2.actor() == null){ Actor ghost = Actor.Create(ActorType.GHOST,t2.row,t2.col); if(ghost != null){ target = ghost; ghost.player_visibility_duration = -1; ghost.target = player; t.color = Color.White; B.Add("A vengeful ghost rises! "); B.PrintAll(); break; } } } } Q.Add(new Event(target,area,100,EventType.TOMBSTONE_GHOST)); } break; } case EventType.POPPIES: { List<Tile> new_area = new List<Tile>(); bool recalculate_distance_map = false; foreach(Tile t in area){ if(t.type == TileType.POPPY_FIELD){ new_area.Add(t); Actor a = t.actor(); if(a == player){ Help.TutorialTip(TutorialTopic.Poppies); } if(a != null && !a.HasAttr(AttrType.NONLIVING,AttrType.PLANTLIKE)){ if(a.attrs[AttrType.POPPY_COUNTER] < 4){ a.GainAttrRefreshDuration(AttrType.POPPY_COUNTER,200); if(a == player && a.attrs[AttrType.POPPY_COUNTER] == 1){ B.Add("You breathe in the overwhelming scent of the poppies. "); //todo: this was set to "no interrupt" before. why? } } else{ a.RefreshDuration(AttrType.POPPY_COUNTER,200); } if(a.attrs[AttrType.POPPY_COUNTER] >= 4){ if(!a.HasAttr(AttrType.ASLEEP,AttrType.JUST_AWOKE)){ if(a.ResistedBySpirit()){ if(player.HasLOS(a)){ B.Add(a.You("resist") + " falling asleep. ",a); } } else{ if(player.HasLOS(a)){ B.Add(a.You("fall") + " asleep in the poppies. ",a); //B.Add("The poppies lull " + a.the_name + " to sleep. ",a); } a.attrs[AttrType.ASLEEP] = R.Between(4,6); } } /*a.ApplyStatus(AttrType.MAGICAL_DROWSINESS,(R.Roll(3)+4)*100); if(a == player && !a.HasAttr(AttrType.MAGICAL_DROWSINESS)){ //B.Add("The poppies make you drowsy. "); Help.TutorialTip(TutorialTopic.Drowsiness); } a.RefreshDuration(AttrType.MAGICAL_DROWSINESS,a.DurationOfMagicalEffect((R.Roll(3)+4)) * 100,a.YouFeel() + " less drowsy. ",a);*/ } } } else{ recalculate_distance_map = true; } } if(new_area.Count > 0){ Q.Add(new Event(new_area,100,EventType.POPPIES)); if(recalculate_distance_map){ M.CalculatePoppyDistanceMap(); } } break; } case EventType.BURROWING: { List<Tile> open = area.Where(x=>x.passable && x.actor() == null); Actor a = target as Actor; if(open.Count > 0){ Tile t = open.Random(); Event e = new Event(a,100,EventType.MOVE); e.tiebreaker = this.tiebreaker; Q.Add(e); a.attrs[AttrType.BURROWING] = 0; a.Move(t.row,t.col); if(player.CanSee(a)){ a.AnimateStorm(1,2,3,'*',Color.Gray); } B.Add(a.TheName(true) + " emerges from the ground. ",a,t); } else{ if(a.HasAttr(AttrType.REGENERATING)){ a.curhp += a.attrs[AttrType.REGENERATING]; if(a.curhp > a.maxhp){ a.curhp = a.maxhp; } } Q.Add(new Event(target,area,100,EventType.BURROWING)); } break; } case EventType.SPAWN_WANDERING_MONSTER: { int spawn_chance = 2; foreach(Actor a in Actor.tiebreakers){ if(a != player && a != null && !a.HasAttr(AttrType.IMMOBILE) && (a.group == null || a.group.Count == 0 || a.group[0] == a)){ spawn_chance *= 2; if(spawn_chance >= 65536){ break; } } } if(R.OneIn(spawn_chance)){ if(M.extra_danger < 8 && R.CoinFlip() && M.current_level != 1){ M.extra_danger++; B.Add("You sense danger. "); } Actor a = M.SpawnWanderingMob(); if(a != null){ a.attrs[AttrType.WANDERING] = 1; a.attrs[AttrType.NO_ITEM] = 1; if(player.CanSee(a)){ B.Add("You suddenly sense the presence of " + a.AName(true) + ". "); } } } Q.Add(new Event(R.Between(20,60)*100,EventType.SPAWN_WANDERING_MONSTER)); break; } /*case EventType.GAS_UPDATE: { int ROWS = Global.ROWS; int COLS = Global.COLS; float[,] g = null; for(int num=0;num<3;++num){ g = new float[ROWS,COLS]; for(int i=1;i<ROWS-1;++i){ for(int j=1;j<COLS-1;++j){ if(M.tile[i,j].passable){ float neighbors_total = 0.0f; int open = 0; foreach(int dir in U.EightDirections){ if(M.tile[i,j].TileInDirection(dir).passable){ pos p = new pos(i,j).PosInDir(dir); neighbors_total += M.gas[p.row,p.col]; ++open; } } if(open > 0){ float avg = neighbors_total / (float)open; float d = 0.03f * open; g[i,j] = M.gas[i,j] * (1-d) + avg * d; } } } } M.gas = g; } for(int i=0;i<ROWS;++i){ for(int j=0;j<COLS;++j){ if(g[i,j] > 0.0f){ if(g[i,j] <= 0.001f){ g[i,j] = 0.0f; M.tile[i,j].features.Remove(FeatureType.POISON_GAS); } else{ g[i,j] -= 0.001f;// * (float)R.r.NextDouble(); M.tile[i,j].features.AddUnique(FeatureType.POISON_GAS); } } else{ M.tile[i,j].features.Remove(FeatureType.POISON_GAS); } } } Q.Add(new Event(100,EventType.GAS_UPDATE)); break; }*/ case EventType.FIRE: { List<Tile> chance_to_burn = new List<Tile>(); //tiles that might be affected List<Tile> chance_to_die_out = new List<Tile>(); //fires that might die out List<PhysicalObject> no_fire = new List<PhysicalObject>(); foreach(PhysicalObject o in new List<PhysicalObject>(Fire.burning_objects)){ if(o.IsBurning()){ foreach(Tile neighbor in o.TilesWithinDistance(1)){ if(neighbor.actor() != null && neighbor.actor() != o){ if(neighbor.actor() == player){ if(!player.HasAttr(AttrType.JUST_SEARED,AttrType.FROZEN,AttrType.DAMAGE_RESISTANCE)){ B.Add("The heat sears you! "); } player.RefreshDuration(AttrType.JUST_SEARED,50); } neighbor.actor().TakeDamage(DamageType.FIRE,DamageClass.PHYSICAL,false,1,null,"searing heat"); } //every actor adjacent to a burning object takes proximity fire damage. (actors never get set on // fire directly this way, but an actor covered in oil will ignite if it takes any fire damage) //every tile adjacent to a burning object has a chance to be affected by fire. oil-covered objects are always affected. //if the roll is passed, fire is applied to the tile. chance_to_burn.AddUnique(neighbor); } if(o is Tile){ chance_to_die_out.AddUnique(o as Tile); } } else{ no_fire.AddUnique(o); } } foreach(Tile t in chance_to_burn){ if(R.OneIn(6) || t.Is(FeatureType.OIL,FeatureType.SPORES,FeatureType.CONFUSION_GAS) || t.Is(TileType.BARREL)){ t.ApplyEffect(DamageType.FIRE); } } foreach(Tile t in chance_to_die_out){ if(!t.Is(TileType.BARREL)){ bool more_flammable_terrain = false; bool more_fire = false; bool final_level_demonic_idol_present = false; //this will soon become a check for any terrain that prevents fires from dying foreach(Tile neighbor in t.TilesAtDistance(1)){ if(neighbor.IsCurrentlyFlammable()){ more_flammable_terrain = true; } if(neighbor.Is(TileType.DEMONIC_IDOL)){ final_level_demonic_idol_present = true; } if(neighbor.IsBurning()){ more_fire = true; } } if(final_level_demonic_idol_present){ continue; //this fire never goes out } int chance = 5; if(more_fire){ chance = 10; } if(more_flammable_terrain){ chance = 20; } if(R.OneIn(chance)){ t.RemoveFeature(FeatureType.FIRE); Fire.burning_objects.Remove(t); if(t.name == "floor" && t.type != TileType.BREACHED_WALL){ t.MakeFloorCharred(); } } } } foreach(PhysicalObject o in no_fire){ Fire.burning_objects.Remove(o); } if(Fire.burning_objects.Count > 0){ Event e = new Event(100,EventType.FIRE); Q.Add(e); Fire.fire_event = e; } else{ Fire.fire_event = null; } break; } } if(msg != ""){ if(msg_objs == null){ B.Add(msg); } else{ if(msg_objs.Count == 1 && msg_objs[0] is Actor && (msg_objs[0] as Actor).HasAttr(AttrType.BURROWING)){ //do nothing } else{ B.Add(msg,msg_objs.ToArray()); } } } } }
public void GettingRandomItemFromListReturnsAnElementFromTheList() { IList<int> list = new List<int>() {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; int rnd = list.Random(); Assert.True(list.Contains(rnd)); }
public void TriggerTrap(bool click) { bool actor_here = (actor() != null); if(actor_here && actor().type == ActorType.CYCLOPEAN_TITAN){ if(name == "floor"){ B.Add(actor().TheName(true) + " smashes " + Tile.Prototype(type).a_name + ". ",this); } else{ B.Add(actor().TheName(true) + " smashes " + the_name + ". ",this); } TransformTo(TileType.FLOOR); return; } if(click){ if(actor() == player || (actor() == null && player.CanSee(this))){ B.Add("*CLICK* ",this); B.PrintAll(); } else{ if(actor() != null && player.CanSee(this) && player.CanSee(actor())){ B.Add("You hear a *CLICK* from under " + actor().the_name + ". "); B.PrintAll(); } else{ if(DistanceFrom(player) <= 12){ B.Add("You hear a *CLICK* nearby. "); B.PrintAll(); } else{ B.Add("You hear a *CLICK* in the distance. "); B.PrintAll(); } } } } if(actor() == player){ Help.TutorialTip(TutorialTopic.Traps); } switch(type){ case TileType.GRENADE_TRAP: { if(actor_here && player.CanSee(actor())){ B.Add("Grenades fall from the ceiling above " + actor().the_name + "! ",this); } else{ B.Add("Grenades fall from the ceiling! ",this); } List<Tile> valid = new List<Tile>(); foreach(Tile t in TilesWithinDistance(1)){ if(t.passable && !t.Is(FeatureType.GRENADE)){ valid.Add(t); } } int count = R.OneIn(10)? 3 : 2; for(;count>0 & valid.Count > 0;--count){ Tile t = valid.Random(); if(t.actor() != null){ if(t.actor() == player){ B.Add("One lands under you! "); } else{ if(player.CanSee(this)){ B.Add("One lands under " + t.actor().the_name + ". ",t.actor()); } } } else{ if(t.inv != null){ B.Add("One lands under " + t.inv.TheName() + ". ",t); } } t.features.Add(FeatureType.GRENADE); valid.Remove(t); Q.Add(new Event(t,100,EventType.GRENADE)); } Toggle(actor()); break; } case TileType.SLIDING_WALL_TRAP: { List<int> dirs = new List<int>(); for(int i=2;i<=8;i+=2){ Tile t = this; bool good = true; while(t.type != TileType.WALL){ t = t.TileInDirection(i); if(t.opaque && t.type != TileType.WALL){ good = false; break; } if(DistanceFrom(t) > 6){ good = false; break; } } if(good && t.row > 0 && t.row < ROWS-1 && t.col > 0 && t.col < COLS-1){ t = t.TileInDirection(i); } else{ good = false; } if(good && t.row > 0 && t.row < ROWS-1 && t.col > 0 && t.col < COLS-1){ foreach(Tile tt in t.TilesWithinDistance(1)){ if(tt.type != TileType.WALL){ good = false; } } } else{ good = false; } if(good){ dirs.Add(i); } } if(dirs.Count == 0){ B.Add("Nothing happens. ",this); } else{ int dir = dirs[R.Roll(dirs.Count)-1]; Tile first = this; while(first.type != TileType.WALL){ first = first.TileInDirection(dir); } first.TileInDirection(dir).TurnToFloor(); ActorType ac = ActorType.SKELETON; if(M.current_level >= 3 && R.CoinFlip()){ ac = ActorType.ZOMBIE; } if(M.current_level >= 9 && R.OneIn(10)){ ac = ActorType.STONE_GOLEM; } if(M.current_level >= 7 && R.PercentChance(1)){ ac = ActorType.MECHANICAL_KNIGHT; } if(M.current_level >= 15 && R.PercentChance(1)){ ac = ActorType.CORPSETOWER_BEHEMOTH; } if(M.current_level >= 15 && R.PercentChance(1)){ ac = ActorType.MACHINE_OF_WAR; } if(R.PercentChance(1)){ first.TileInDirection(dir).TransformTo(TileType.CHEST); if(R.PercentChance(1)){ first.TileInDirection(dir).color = Color.Yellow; } } else{ Actor.Create(ac,first.TileInDirection(dir).row,first.TileInDirection(dir).col,TiebreakerAssignment.InsertAfterCurrent); } first.TurnToFloor(); foreach(Tile t in first.TileInDirection(dir).TilesWithinDistance(1)){ t.solid_rock = false; } if(first.ActorInDirection(dir) != null){ first.ActorInDirection(dir).FindPath(first.TileInDirection(dir.RotateDir(true,4))); //first.ActorInDirection(dir).FindPath(TileInDirection(dir)); } if(player.CanSee(first)){ B.Add("The wall slides away. "); } else{ if(DistanceFrom(player) <= 6){ B.Add("You hear rock sliding on rock. "); } } } Toggle(actor()); break; } case TileType.TELEPORT_TRAP: { if(actor_here){ B.Add("An unstable energy covers " + actor().TheName(true) + ". ",actor()); actor().attrs[AttrType.TELEPORTING] = R.Roll(4); Q.KillEvents(actor(),AttrType.TELEPORTING); //should be replaced by refreshduration eventually. works the same way, though. Q.Add(new Event(actor(),(R.Roll(10)+25)*100,AttrType.TELEPORTING,actor().YouFeel() + " more stable. ",actor())); } else{ if(inv != null){ B.Add("An unstable energy covers " + inv.TheName(true) + ". ",this); Tile dest = M.AllTiles().Where(x=>x.passable && x.CanGetItem()).RandomOrDefault(); if(dest != null){ B.Add("It vanishes! ",this); bool seen = player.CanSee(this); Item i = inv; inv = null; dest.GetItem(i); if(seen){ B.Add("It reappears! ",dest); } else{ B.Add(i.AName(true) + " appears! ",dest); } } else{ B.Add("Nothing happens. ",this); } } else{ B.Add("An unstable energy crackles for a moment, then dissipates. ",this); } } Toggle(actor()); break; } case TileType.SHOCK_TRAP: { //int old_radius = light_radius; //This was a cool effect, but caused bugs when the tile's radius changed mid-trigger. //UpdateRadius(old_radius,3,true); //I'll restore it when I figure out how... if(actor_here){ if(player.CanSee(actor())){ B.Add("Electricity zaps " + actor().the_name + ". ",this); } if(actor().TakeDamage(DamageType.ELECTRIC,DamageClass.PHYSICAL,R.Roll(3,6),null,"a shock trap")){ actor().ApplyStatus(AttrType.STUNNED,(R.Roll(6)+7)*100); /*B.Add(actor().YouAre() + " stunned! ",actor()); actor().RefreshDuration(AttrType.STUNNED,actor().DurationOfMagicalEffect(R.Roll(6)+7)*100,(actor().YouAre() + " no longer stunned. "),actor());*/ if(actor() == player){ Help.TutorialTip(TutorialTopic.Stunned); } } } else{ B.Add("Arcs of electricity appear and sizzle briefly. ",this); //apply electricity, once wands have been added } //M.Draw(); //UpdateRadius(3,old_radius,true); Toggle(actor()); break; } case TileType.LIGHT_TRAP: if(M.wiz_lite == false){ if(actor_here && player.HasLOS(row,col) && !actor().IsHiddenFrom(player)){ B.Add("A wave of light washes out from above " + actor().TheName(true) + "! "); } else{ B.Add("A wave of light washes over the area! "); } M.wiz_lite = true; M.wiz_dark = false; Q.KillEvents(null,EventType.NORMAL_LIGHTING); Q.Add(new Event((R.Roll(2,20) + 120) * 100,EventType.NORMAL_LIGHTING)); } else{ B.Add("The air grows even brighter for a moment. "); Q.KillEvents(null,EventType.NORMAL_LIGHTING); Q.Add(new Event((R.Roll(2,20) + 120) * 100,EventType.NORMAL_LIGHTING)); } Toggle(actor()); break; case TileType.DARKNESS_TRAP: if(M.wiz_dark == false){ if(actor_here && player.CanSee(actor())){ B.Add("A surge of darkness radiates out from above " + actor().TheName(true) + "! "); if(player.light_radius > 0){ B.Add("Your light is extinguished! "); } } else{ B.Add("A surge of darkness radiates over the area! "); if(player.light_radius > 0){ B.Add("Your light is extinguished! "); } } M.wiz_dark = true; M.wiz_lite = false; Q.KillEvents(null,EventType.NORMAL_LIGHTING); Q.Add(new Event((R.Roll(2,20) + 120) * 100,EventType.NORMAL_LIGHTING)); } else{ B.Add("The air grows even darker for a moment. "); Q.KillEvents(null,EventType.NORMAL_LIGHTING); Q.Add(new Event((R.Roll(2,20) + 120) * 100,EventType.NORMAL_LIGHTING)); } Toggle(actor()); break; case TileType.FIRE_TRAP: { if(actor_here){ B.Add("A column of flame engulfs " + actor().TheName(true) + "! ",this); actor().ApplyBurning(); } else{ B.Add("A column of flame appears! ",this); } AddFeature(FeatureType.FIRE); Toggle(actor()); break; } case TileType.ALARM_TRAP: if(actor() == player){ B.Add("A high-pitched ringing sound reverberates from above you. "); } else{ if(actor_here && player.CanSee(actor())){ B.Add("A high-pitched ringing sound reverberates from above " + actor().the_name + ". "); } else{ B.Add("You hear a high-pitched ringing sound. "); } } foreach(Actor a in ActorsWithinDistance(12,true)){ if(a.type != ActorType.GIANT_BAT && a.type != ActorType.BLOOD_MOTH && a.type != ActorType.CARNIVOROUS_BRAMBLE && a.type != ActorType.LASHER_FUNGUS && a.type != ActorType.PHASE_SPIDER){ a.FindPath(this); } } Toggle(actor()); break; case TileType.BLINDING_TRAP: if(actor_here){ B.Add("A dart flies out and strikes " + actor().TheName(true) + ". ",this); //todo: what about replacing this with blinding dust? if(!actor().HasAttr(AttrType.NONLIVING,AttrType.BLINDSIGHT)){ actor().ApplyStatus(AttrType.BLIND,(R.Roll(2,6)+6)*100); /*B.Add(actor().YouAre() + " blind! ",actor()); actor().RefreshDuration(AttrType.BLIND,(R.Roll(3,6) + 6) * 100,actor().YouAre() + " no longer blinded. ",actor());*/ } else{ B.Add("It doesn't affect " + actor().the_name + ". ",actor()); } } else{ B.Add("A dart flies out and hits the floor. ",this); } Toggle(actor()); break; case TileType.ICE_TRAP: if(actor_here){ if(!actor().IsBurning()){ if(player.CanSee(this)){ B.Add("The air suddenly freezes around " + actor().TheName(true) + ". "); } actor().ApplyFreezing(); } else{ if(player.CanSee(this)){ if(player.CanSee(actor())){ B.Add("Ice crystals form in the air around " + actor().the_name + " but quickly vanish. "); } else{ B.Add("Ice crystals form in the air but quickly vanish. "); } } } } else{ B.Add("Ice crystals form in the air but quickly vanish. "); } Toggle(actor()); break; case TileType.PHANTOM_TRAP: { Tile open = TilesWithinDistance(3).Where(t => t.passable && t.actor() == null && t.HasLOE(this)).RandomOrDefault(); if(open != null){ Actor a = Actor.CreatePhantom(open.row,open.col); if(a != null){ a.attrs[AttrType.PLAYER_NOTICED]++; a.player_visibility_duration = -1; if(player.HasLOS(a)){ //don't print a message if you're just detecting monsters B.Add("A ghostly image rises! ",a); } } else{ B.Add("Nothing happens. ",this); } } else{ B.Add("Nothing happens. ",this); } Toggle(actor()); break; } case TileType.POISON_GAS_TRAP: { bool spores = false; if(M.current_level >= 5 && R.PercentChance((M.current_level - 4) * 3)){ //spores = true; //3% at level 5...33% at level 15...48% at level 20. - disabled for now } int num = R.Roll(5) + 8; if(spores){ List<Tile> new_area = AddGaseousFeature(FeatureType.SPORES,num); //todo: should this be its own trap type? what about other gases? if(new_area.Count > 0){ B.Add("A cloud of spores fills the area! ",this); Event.RemoveGas(new_area,600,FeatureType.SPORES,12); } } else{ List<Tile> new_area = AddGaseousFeature(FeatureType.POISON_GAS,num); if(new_area.Count > 0){ B.Add("Poisonous gas fills the area! ",this); Event.RemoveGas(new_area,300,FeatureType.POISON_GAS,18); } } Toggle(actor()); break; } case TileType.SCALDING_OIL_TRAP: { if(actor_here){ B.Add("Scalding oil pours over " + actor().TheName(true) + "! ",this); if(actor().TakeDamage(DamageType.FIRE,DamageClass.PHYSICAL,R.Roll(3,6),null,"a scalding oil trap")){ if(!actor().HasAttr(AttrType.BURNING,AttrType.SLIMED) && !IsBurning()){ actor().attrs[AttrType.OIL_COVERED] = 1; B.Add(actor().YouAre() + " covered in oil. ",actor()); if(actor() == player){ Help.TutorialTip(TutorialTopic.Oiled); } } } } else{ B.Add("Scalding oil pours over the floor. ",this); } List<Tile> covered_in_oil = new List<Tile>{this}; List<Tile> added = new List<Tile>(); for(int i=0;i<2;++i){ foreach(Tile t in covered_in_oil){ foreach(int dir in U.FourDirections){ Tile neighbor = t.TileInDirection(dir); if(neighbor.DistanceFrom(this) == 1 && R.OneIn(3) && neighbor.passable && !covered_in_oil.Contains(neighbor)){ added.AddUnique(neighbor); } } } covered_in_oil.AddRange(added); } foreach(Tile t in covered_in_oil){ t.AddFeature(FeatureType.OIL); } Toggle(actor()); break; } case TileType.FLING_TRAP: { List<int> valid_dirs = new List<int>(); foreach(int d in U.EightDirections){ bool good = true; Tile current = this; for(int i=0;i<2;++i){ current = current.TileInDirection(d); if(current == null || (!current.passable && !current.Is(TileType.BARREL,TileType.CRACKED_WALL,TileType.DOOR_C,TileType.HIDDEN_DOOR,TileType.POISON_BULB,TileType.STANDING_TORCH))){ good = false; //try to pick directions that are either open, or that have interesting things to be knocked into break; } } if(good){ valid_dirs.Add(d); } } Toggle(actor()); int dir = -1; if(valid_dirs.Count > 0){ dir = valid_dirs.Random(); } else{ dir = Global.RandomDirection(); } if(actor_here){ Actor a = actor(); B.Add("The floor suddenly tilts up under " + a.TheName(true) + "! ",this); a.attrs[AttrType.TURN_INTO_CORPSE]++; KnockObjectBack(actor(),GetBestExtendedLineOfEffect(TileInDirection(dir)),5,null); a.CorpseCleanup(); } else{ if(inv != null){ B.Add("The floor suddenly tilts up under " + inv.TheName(true) + "! ",this); string item_name = "it"; string punctuation = ". "; if(!player.CanSee(this)){ item_name = inv.AName(true); punctuation = "! "; } Item i = inv; inv = null; List<Tile> line = GetBestExtendedLineOfEffect(TileInDirection(dir)); if(line.Count > 13){ line = line.ToCount(13); //for range 12 } Tile t = line.LastBeforeSolidTile(); Actor first = FirstActorInLine(line); if(first != null){ t = first.tile(); B.Add(item_name + " hits " + first.the_name + punctuation,first); } line = line.ToFirstSolidTileOrActor(); if(line.Count > 0){ line.RemoveAt(line.Count - 1); } { Tile first_unseen = null; foreach(Tile tile2 in line){ if(!tile2.seen){ first_unseen = tile2; break; } } if(first_unseen != null){ line = line.To(first_unseen); if(line.Count > 0){ line.RemoveAt(line.Count - 1); } } } M.Draw(); if(line.Count > 0){ Screen.AnimateProjectile(line,new colorchar(i.symbol,i.color)); } if(i.IsBreakable()){ B.Add("It breaks! ",t); i.CheckForMimic(); } else{ t.GetItem(i); } t.MakeNoise(2); if(first != null){ //first.player_visibility_duration = -1; //not sure how angry monsters should get in this case //first.attrs[AttrType.PLAYER_NOTICED]++; } else{ if(t.IsTrap()){ t.TriggerTrap(); } } } else{ B.Add("Nothing happens. ",this); } } break; } case TileType.STONE_RAIN_TRAP: B.Add("Stones fall from the ceiling! ",this); if(actor_here){ Actor a = actor(); B.Add(a.YouVisibleAre() + " hit! ",this); a.TakeDamage(DamageType.NORMAL,DamageClass.PHYSICAL,R.Roll(3,6),null,"falling stones"); } Toggle(actor()); foreach(Tile neighbor in TilesWithinDistance(1).Randomize()){ if(R.PercentChance(40)){ if(neighbor.IsTrap()){ B.Add("A bouncing stone triggers a trap. ",neighbor); } neighbor.ApplyEffect(DamageType.NORMAL); //break items and set off traps if(neighbor.Is(TileType.FLOOR)){ neighbor.Toggle(null,TileType.GRAVEL); neighbor.RemoveFeature(FeatureType.SLIME); neighbor.RemoveFeature(FeatureType.OIL); } } } break; default: break; } }
public List<Tile> AddGaseousFeature(FeatureType f,int num) { List<Tile> area = new List<Tile>(); Tile current = this; for(int i=0;i<num;++i){ if(!current.Is(f)){ current.AddFeature(f); area.Add(current); } else{ for(int tries=0;tries<50;++tries){ List<Tile> open = new List<Tile>(); foreach(Tile t in current.TilesAtDistance(1)){ if(t.passable){ open.Add(t); if(!t.Is(f)){ open.Add(t); //3x as likely if it can expand there open.Add(t); } } } /*foreach(int dir in U.FourDirections){ if(current.TileInDirection(dir).passable){ open.Add(current.TileInDirection(dir)); } }*/ if(open.Count > 0){ Tile possible = open.Random(); if(!possible.Is(f)){ possible.AddFeature(f); area.Add(possible); break; } else{ current = possible; } } else{ break; } } } } return area; }
public void OpenChest() { if(type == TileType.CHEST){ if(spellbooks_generated < 5 && R.OneIn(50)){ //keep an eye on this value ++spellbooks_generated; SpellType spell = SpellType.NO_SPELL; List<SpellType> random_spell_list = new List<SpellType>(); foreach(SpellType sp in Enum.GetValues(typeof(SpellType))){ random_spell_list.Add(sp); } while(spell == SpellType.NO_SPELL && random_spell_list.Count > 0){ SpellType sp = random_spell_list.RemoveRandom(); if(!player.HasSpell(sp) && sp != SpellType.NO_SPELL && sp != SpellType.NUM_SPELLS){ spell = sp; } } if(spell != SpellType.NO_SPELL){ B.Add("You find a spellbook! "); B.Add("You learn " + Spell.Name(spell) + ". "); player.spells[spell] = true; Actor.spells_in_order.Add(spell); } else{ B.Add("The chest is empty! "); } } else{ ConsumableType item = Item.RandomChestItem(); if(item == ConsumableType.MAGIC_TRINKET){ List<MagicTrinketType> valid = new List<MagicTrinketType>(); foreach(MagicTrinketType trinket in Enum.GetValues(typeof(MagicTrinketType))){ if(trinket != MagicTrinketType.NO_MAGIC_TRINKET && trinket != MagicTrinketType.NUM_MAGIC_TRINKETS && !player.magic_trinkets.Contains(trinket)){ valid.Add(trinket); } } if(valid.Count > 0){ MagicTrinketType trinket = valid.Random(); if(trinket == MagicTrinketType.BRACERS_OF_ARROW_DEFLECTION || trinket == MagicTrinketType.BOOTS_OF_GRIPPING){ B.Add("You find " + MagicTrinket.Name(trinket) + "! "); } else{ B.Add("You find a " + MagicTrinket.Name(trinket) + "! "); } player.magic_trinkets.Add(trinket); Help.TutorialTip(TutorialTopic.MagicTrinkets); } else{ B.Add("The chest is empty! "); } } else{ bool no_room = false; if(player.InventoryCount() >= Global.MAX_INVENTORY_SIZE){ no_room = true; } Item i = Item.Create(Item.RandomItem(),player); if(i != null){ i.revealed_by_light = true; B.Add("You find " + Item.Prototype(i.type).AName() + ". "); if(no_room){ B.Add("Your pack is too full to pick it up. "); i.ignored = true; } } } } if(color == Color.Yellow){ B.Add("There's something else in the chest! "); color = Color.DarkYellow; } else{ TurnToFloor(); } } }
private void GetNextArea(int idx, int step, Block block) { var possibleAreas = new List<long>(); FillPossibleAreas(idx, step, block, possibleAreas); Area = possibleAreas.Random(); }
/// <summary> /// Uses WM, attacking targets. /// </summary> /// <param name="attacker"></param> /// <param name="skill"></param> /// <param name="targetAreaId"></param> /// <param name="unkInt1"></param> /// <param name="unkInt2"></param> public void Use(Creature attacker, Skill skill, long targetAreaId = 0, int unkInt1 = 0, int unkInt2 = 0) { bool wasKnockedDown = (attacker.IsKnockedDown || attacker.WasKnockedBack); if ((attacker.Stun > 500 && wasKnockedDown || attacker.IsStunned && !wasKnockedDown || DateTime.Now.AddMilliseconds(2000) < attacker.AttackDelayTime && (wasKnockedDown)) && attacker.InterceptingSkillId == SkillId.None) { Send.SkillUseSilentCancel(attacker); return; } var range = this.GetRange(attacker, skill); ICollection<Creature> targets = attacker.GetTargetableCreaturesInRange(range, true).Where(t => !(DateTime.Now.AddMilliseconds(2000) < t.NotReadyToBeHitTime)).ToList(); //Able to be attacked at 1/3 of knock down time. // Check targets if (targets.Count == 0) { Send.Notice(attacker, Localization.Get("There isn't a target nearby to use that on.")); Send.SkillUseSilentCancel(attacker); return; } // Create actions var cap = new CombatActionPack(attacker, skill.Info.Id); var aAction = new AttackerAction(CombatActionType.SpecialHit, attacker, skill.Info.Id, targetAreaId); aAction.Set(AttackerOptions.Result); cap.Add(aAction); var survived = new List<Creature>(); var skipped = new List<Creature>(); var i = 0; foreach (var target in targets) { i++; target.StopMove(); Skill smash = target.Skills.Get(SkillId.Smash); if (smash != null && target.Skills.IsReady(SkillId.Smash) && !attacker.IsPlayer) attacker.InterceptingSkillId = SkillId.Smash; TargetAction tAction; if (attacker.InterceptingSkillId == SkillId.Smash && target.GetPosition().InRange(attacker.GetPosition(), target.AttackRangeFor(attacker))) { aAction.Options |= AttackerOptions.Result; tAction = new TargetAction(CombatActionType.CounteredHit, target, attacker, SkillId.Smash); tAction.Options |= TargetOptions.Result; } else { tAction = new TargetAction(CombatActionType.TakeHit, target, attacker, skill.Info.Id); } attacker.InterceptingSkillId = SkillId.None; tAction.Delay = 300; // Usually 300, sometimes 350? // Calculate damage float damage = 0f; if (attacker.RightHand != null && ( attacker.RightHand.Data.HasTag("/weapon/bow01/") || attacker.RightHand.Data.HasTag("/weapon/bow/") || attacker.RightHand.Data.HasTag("/weapon/crossbow/") || attacker.RightHand.Data.HasTag("/weapon/shuriken/") || attacker.RightHand.Data.HasTag("/weapon/atlatl/") || attacker.RightHand.Data.HasTag("/weapon/gun/dualgun/"))) { damage = attacker.GetRndBareHandDamage(); } else { damage = attacker.GetRndTotalDamage(); } damage *= skill.RankData.Var1 / 100f; // Handle skills and reductions var allCrit = false; var critSkill = target.Skills.Get(SkillId.CriticalHit); if (allCrit) { // Add crit bonus var bonus = critSkill.RankData.Var1 / 100f; damage = damage + (damage * bonus); // Set target option tAction.Set(TargetOptions.Critical); } else if (i == 1) { CriticalHit.Handle(attacker, attacker.GetTotalCritChance(0), ref damage, tAction); if (tAction.Has(TargetOptions.Critical)) allCrit = true; } var maxDamage = damage; //Damage without Defense and Protection SkillHelper.HandleDefenseProtection(target, ref damage); Defense.Handle(aAction, tAction, ref damage); ManaShield.Handle(target, ref damage, tAction, maxDamage); // Clean Hit if not defended nor critical if (!tAction.Is(CombatActionType.Defended) && !tAction.Has(TargetOptions.Critical)) tAction.Set(TargetOptions.CleanHit); // Take damage if any is left if (damage > 0) target.TakeDamage(tAction.Damage = damage, attacker); // Finish if dead, knock down if not defended if (target.IsDead) tAction.Set(TargetOptions.KnockDownFinish); else if (!tAction.Is(CombatActionType.Defended)) tAction.Set(TargetOptions.KnockDown); // Anger Management if (!target.IsDead) survived.Add(target); if (target.UseBattleStanceFromAOE) target.IsInBattleStance = true; // Stun & knock back aAction.Stun = CombatMastery.GetAttackerStun(attacker.AverageKnockCount, attacker.AverageAttackSpeed, true); if (!tAction.Is(CombatActionType.Defended)) { tAction.Stun = CombatMastery.GetTargetStun(attacker.AverageKnockCount, attacker.AverageAttackSpeed, true); target.Stability = Creature.MinStability; attacker.Shove(target, KnockbackDistance); } // Add action cap.Add(tAction); } // Only select a random aggro if there is no aggro yet, // WM only aggroes one target at a time. if (survived.Count != 0 && attacker.Region.CountAggro(attacker) < 1) { var rnd = RandomProvider.Get(); var aggroTarget = survived.Random(); aggroTarget.Aggro(attacker); } // Reduce life in old combat system if (!AuraData.FeaturesDb.IsEnabled("CombatSystemRenewal")) { var amount = (attacker.LifeMax < 10 ? 2 : attacker.LifeMax / 10); attacker.ModifyLife(-amount); attacker.InvincibilityTime = DateTime.Now.AddMilliseconds(2300); } // Spin it~ Send.UseMotion(attacker, 8, 4); cap.Handle(); Send.SkillUse(attacker, skill.Info.Id, targetAreaId, unkInt1, unkInt2); skill.Stacks = 0; }
private static void GenerateComments(List<int> articles, List<string> users) { Parallel.ForEach(articles,new ParallelOptions{ MaxDegreeOfParallelism = 30} , articleId => { var commentsList = new List<Comment>(); var random = new Random(); var viewCount = random.Next(5, 60); Console.WriteLine("Proccessing Comments ArticleId: {0}, Comments Count: {1}", articleId, viewCount); for (int i = 0; i < viewCount; i++) { var comment = new Comment { ArticleId = articleId, Stamp = Guid.NewGuid(), CreatedDate = DateTime.UtcNow.AddDays(0 - random.Next(5, 100)) .AddHours(0 - random.Next(0, 24)) .AddMinutes(0 - random.Next(0, 60)), AuthorId = users.Random(), Body = SeedExtensions.Headers.Random() + " " + SeedExtensions.Headers.Random() }; commentsList.Add(comment); } try { using (var context = new ApplicationDbContext()) { var commentEnity = (DbSet<Comment>) context.Comments; commentEnity.AddRange(commentsList); context.SaveChanges(); } } catch (Exception exception) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("ERROR Proccessing Comments ArticleId: {0}", articleId); Console.WriteLine(exception.Message); if (exception.InnerException != null) { Console.WriteLine(exception.InnerException.Message); } Console.ResetColor(); } }); }
/// <summary> /// The neighbour with the most empty space. Otherwise picks at random /// </summary> /// <returns>The emptiest nieghbour.</returns> private Neighbours FindEmptiestNieghbour() { var neighbourPop = new List<KeyValuePair<Neighbours, int>>(4); var directions = Enum.GetValues(typeof(Neighbours)).Cast<Neighbours>().ToList(); foreach(var dir in directions) { var n = this[dir]; if(n != null) { var space = n.maxPopulation - n.population.Count; neighbourPop.Add(new KeyValuePair<Neighbours, int>(dir, space)); } } neighbourPop.Sort( (a, b) => a.Value.CompareTo(b.Value) ); bool allTheSame = true; int value = neighbourPop[0].Value; if(neighbourPop.Count > 1) { for (int i = 1; i < neighbourPop.Count; i++) { var t = neighbourPop[i].Value; if(t != value) { allTheSame = false; break; } } } if(allTheSame) return neighbourPop.Random().Key; else return neighbourPop[neighbourPop.Count-1].Key; //Last has most space }
public void AlterRooms(int no_change_freq,int add_pillars_freq,int cross_room_freq,int cave_widen_freq,int cave_fill_freq) { List<int> modification = new List<int>(); for(int i=0;i<no_change_freq;++i){ modification.Add(0); } for(int i=0;i<add_pillars_freq;++i){ modification.Add(1); } for(int i=0;i<cross_room_freq;++i){ modification.Add(2); } for(int i=0;i<cave_widen_freq;++i){ modification.Add(3); } for(int i=0;i<cave_fill_freq;++i){ modification.Add(4); } if(modification.Count == 0){ return; } ForEachRectangularRoom((start_r,start_c,end_r,end_c) => { int mod = modification.Random(); switch(mod){ case 0: return true; case 1: { int height = end_r - start_r + 1; int width = end_c - start_c + 1; if(height > 3 || width > 3){ List<PillarArrangement> layouts = new List<PillarArrangement>(); if(height % 2 == 1 && width % 2 == 1){ layouts.Add(PillarArrangement.Single); } if((height % 2 == 1 || width % 2 == 1) && height != 4 && width != 4){ layouts.Add(PillarArrangement.Row); } if(height >= 5 && width >= 5){ layouts.Add(PillarArrangement.Corners); } if(height > 2 && width > 2 && height != 4 && width != 4){ layouts.Add(PillarArrangement.Full); } if((width % 2 == 1 && width >= 5) || (height % 2 == 1 && height >= 5)){ layouts.Add(PillarArrangement.StatueEdges); } if(layouts.Count == 0 || CoinFlip()){ //otherwise they're too common layouts.Add(PillarArrangement.StatueCorners); } if(layouts.Count > 0){ CellType pillar = CellType.Pillar; switch(layouts.Random()){ case PillarArrangement.Single: map[(start_r + end_r)/2,(start_c + end_c)/2] = pillar; break; case PillarArrangement.Row: { bool vertical; if(width % 2 == 1 && height % 2 == 0){ vertical = true; } else{ if(height % 2 == 1 && width % 2 == 0){ vertical = false; } else{ vertical = CoinFlip(); } } if(vertical){ if(height % 2 == 1){ for(int i=start_r+1;i<=end_r-1;i+=2){ map[i,(start_c + end_c)/2] = pillar; } } else{ int offset = 0; if(height % 4 == 0){ offset = Roll(2) - 1; } for(int i=start_r+1+offset;i<(start_r + end_r)/2;i+=2){ map[i,(start_c + end_c)/2] = pillar; } for(int i=end_r-1-offset;i>(start_r + end_r)/2+1;i-=2){ map[i,(start_c + end_c)/2] = pillar; } } } else{ if(width % 2 == 1){ for(int i=start_c+1;i<=end_c-1;i+=2){ map[(start_r + end_r)/2,i] = pillar; } } else{ int offset = 0; if(width % 4 == 0){ offset = Roll(2) - 1; } for(int i=start_c+1+offset;i<(start_c + end_c)/2;i+=2){ map[(start_r + end_r)/2,i] = pillar; } for(int i=end_c-1-offset;i>(start_c + end_c)/2+1;i-=2){ map[(start_r + end_r)/2,i] = pillar; } } } break; } case PillarArrangement.Corners: { int v_offset = 0; int h_offset = 0; if(height % 4 == 0){ v_offset = Roll(2) - 1; } if(width % 4 == 0){ h_offset = Roll(2) - 1; } map[start_r + 1 + v_offset,start_c + 1 + h_offset] = pillar; map[start_r + 1 + v_offset,end_c - 1 - h_offset] = pillar; map[end_r - 1 - v_offset,start_c + 1 + h_offset] = pillar; map[end_r - 1 - v_offset,end_c - 1 - h_offset] = pillar; break; } case PillarArrangement.Full: { int v_offset = 0; int h_offset = 0; if(height % 4 == 0){ v_offset = Roll(2) - 1; } if(width % 4 == 0){ h_offset = Roll(2) - 1; } int half_r = (start_r + end_r)/2; int half_c = (start_c + end_c)/2; int half_r_offset = (start_r + end_r + 1)/2; int half_c_offset = (start_c + end_c + 1)/2; for(int i=start_r+1+v_offset;i<half_r;i+=2){ for(int j=start_c+1+h_offset;j<half_c;j+=2){ map[i,j] = pillar; } } for(int i=start_r+1+v_offset;i<half_r;i+=2){ for(int j=end_c-1-h_offset;j>half_c_offset;j-=2){ map[i,j] = pillar; } } for(int i=end_r-1-v_offset;i>half_r_offset;i-=2){ for(int j=start_c+1+h_offset;j<half_c;j+=2){ map[i,j] = pillar; } } for(int i=end_r-1-v_offset;i>half_r_offset;i-=2){ for(int j=end_c-1-h_offset;j>half_c_offset;j-=2){ map[i,j] = pillar; } } if((width+1) % 4 == 0){ if(height % 2 == 1){ for(int i=start_r+1;i<=end_r-1;i+=2){ map[i,half_c] = pillar; } } else{ int offset = 0; if(height % 4 == 0){ offset = Roll(2) - 1; } for(int i=start_r+1+offset;i<half_r;i+=2){ map[i,half_c] = pillar; } for(int i=end_r-1-offset;i>half_r_offset;i-=2){ map[i,half_c] = pillar; } } } if((height+1) % 4 == 0){ if(width % 2 == 1){ for(int i=start_c+1;i<=end_c-1;i+=2){ map[half_r,i] = pillar; } } else{ int offset = 0; if(width % 4 == 0){ offset = Roll(2) - 1; } for(int i=start_c+1+offset;i<half_c;i+=2){ map[half_r,i] = pillar; } for(int i=end_c-1-offset;i>half_c_offset;i-=2){ map[half_r,i] = pillar; } } } break; } case PillarArrangement.StatueCorners: map[start_r,start_c] = CellType.Statue; map[start_r,end_c] = CellType.Statue; map[end_r,start_c] = CellType.Statue; map[end_r,end_c] = CellType.Statue; break; case PillarArrangement.StatueEdges: { map[start_r,start_c] = CellType.Statue; map[start_r,end_c] = CellType.Statue; map[end_r,start_c] = CellType.Statue; map[end_r,end_c] = CellType.Statue; if(width % 2 == 1 && width > 3){ int half_c = (start_c + end_c)/2; int corridors = new pos(start_r,half_c).CardinalAdjacentPositions().Where(x => BoundsCheck(x) && map[x].IsCorridorType()).Count; if(corridors == 0){ map[start_r,half_c] = CellType.Statue; } corridors = new pos(end_r,half_c).CardinalAdjacentPositions().Where(x => BoundsCheck(x) && map[x].IsCorridorType()).Count; if(corridors == 0){ map[end_r,half_c] = CellType.Statue; } } if(height % 2 == 1 && height > 3){ int half_r = (start_r + end_r)/2; int corridors = new pos(half_r,start_c).CardinalAdjacentPositions().Where(x => BoundsCheck(x) && map[x].IsCorridorType()).Count; if(corridors == 0){ map[half_r,start_c] = CellType.Statue; } corridors = new pos(half_r,end_c).CardinalAdjacentPositions().Where(x => BoundsCheck(x) && map[x].IsCorridorType()).Count; if(corridors == 0){ map[half_r,end_c] = CellType.Statue; } } break; } default: break; } } } return true; } case 2: { int height = end_r - start_r + 1; int width = end_c - start_c + 1; if(height < 4 || width < 4){ //nothing happens until we get above 4x4 return true; } int rows_to_convert = Roll((height/2)-1); int cols_to_convert = Roll((width/2)-1); if(rows_to_convert == 1 && cols_to_convert == 1){ return true; } List<pos> blocked = new List<pos>(); for(int i=start_r;i<=end_r;++i){ for(int j=start_c;j<=end_c;++j){ if((i < start_r + rows_to_convert || i > end_r - rows_to_convert) && (j < start_c + cols_to_convert || j > end_c - cols_to_convert)){ pos p = new pos(i,j); foreach(pos neighbor in p.CardinalAdjacentPositions()){ if(map[neighbor].IsCorridorType()){ blocked.Add(p); } } map[i,j] = CellType.Wall; } } } blocked.Randomize(); foreach(pos p in blocked){ bool done = false; foreach(pos neighbor in p.CardinalAdjacentPositions()){ if(map[neighbor].IsRoomType()){ map[p] = CellType.RoomInterior; done = true; break; } } if(!done){ List<int> valid_dirs = new List<int>(); foreach(int dir in U.FourDirections){ pos next = p.PosInDir(dir); while(next.row >= start_r && next.row <= end_r && next.col >= start_c && next.col <= end_c){ if(next.CardinalAdjacentPositions().Any(x=>map[x].IsRoomType())){ valid_dirs.Add(dir); break; } next = next.PosInDir(dir); } } int valid_dir = valid_dirs.RandomOrDefault(); pos next2 = p.PosInDir(valid_dir); List<pos> new_corridor = new List<pos>{p}; while(true){ new_corridor.Add(next2); if(next2.CardinalAdjacentPositions().Any(x=>map[x].IsRoomType())){ break; } next2 = next2.PosInDir(valid_dir); } foreach(pos p2 in new_corridor){ map[p2] = CellType.RoomInterior; } } } return true; } case 3: { List<pos> list = map.PositionsWhere(x=>x.row >= start_r && x.row <= end_r && x.col >= start_c && x.col <= end_c); PosArray<CellType> old_map = new PosArray<CellType>(H,W); foreach(pos p in list){ old_map[p] = map[p]; map[p] = CellType.Wall; } PosArray<bool> rock = new PosArray<bool>(H,W); for(int i=0;i<H;++i){ for(int j=0;j<W;++j){ pos p = new pos(i,j); rock[p] = true; if(BoundsCheck(i,j,false)){ foreach(pos neighbor in p.AdjacentPositionsClockwise()){ if(map[neighbor] != CellType.Wall){ rock[p] = false; break; } } } } } foreach(pos p in list){ map[p] = CellType.RoomInterior; //todo: might this step be extraneous? } List<pos> frontier = new List<pos>(); { PosArray<bool> in_list = new PosArray<bool>(H,W); foreach(pos p in list){ in_list[p] = true; } for(int i=0;i<H;++i){ for(int j=0;j<W;++j){ pos p = new pos(i,j); if(in_list[p]){ foreach(pos neighbor in p.PositionsAtDistance(1,in_list)){ if(!in_list[neighbor]){ frontier.Add(p); break; } } } } } } int fail_counter = 0; int num_added = 0; bool finished = false; while(!finished){ if(frontier.Count == 0 || num_added >= 30){ //todo check this value finished = true; break; } pos f = frontier.RemoveRandom(); foreach(pos neighbor in f.CardinalAdjacentPositions()){ if(!BoundsCheck(neighbor,false) || !rock[neighbor.row,neighbor.col]){ ++fail_counter; //this might now be unreachable if(!BoundsCheck(neighbor,false)){ fail_counter += 25; //fail quicker when against the edge of the map to prevent ugliness } //however, this doesn't actually fail as quickly as it should - i've overlooked something. if(fail_counter >= 50){ finished = true; break; } } else{ if(map[neighbor] != CellType.RoomInterior){ map[neighbor] = CellType.RoomInterior; ++num_added; bool add_neighbor = true; foreach(pos n2 in neighbor.CardinalAdjacentPositions()){ if(!BoundsCheck(n2,false) || !rock[n2.row,n2.col]){ add_neighbor = false; ++fail_counter; //this might now be unreachable if(!BoundsCheck(neighbor,false)){ fail_counter += 25; //fail quicker when against the edge of the map to prevent ugliness } //however, this doesn't actually fail as quickly as it should - i've overlooked something. if(fail_counter >= 50){ finished = true; } break; } } if(finished){ break; } if(add_neighbor){ frontier.Add(neighbor); } } } } } foreach(pos p in list){ map[p] = old_map[p]; } return true; } case 4: { List<pos> list = map.PositionsWhere(x=>x.row >= start_r && x.row <= end_r && x.col >= start_c && x.col <= end_c); Dungeon room = new Dungeon((end_r - start_r) + 3,(end_c - start_c) + 3); //includes borders List<pos> map_exits = list.Where(x=>x.CardinalAdjacentPositions().Any(y=>map[y].IsCorridorType())); //grab the positions from list that have any adjacent corridor-type cells if(map_exits.Count < 2){ return true; } List<pos> room_exits = new List<pos>(); foreach(pos exit in map_exits){ room_exits.Add(new pos(exit.row-start_r+1,exit.col-start_c+1)); } int tries = 0; while(true){ room.FillWithRandomWalls(25); room.ApplyCellularAutomataXYRule(3); room.ConnectDiagonals(); room.RemoveDeadEndCorridors(); room.RemoveUnconnectedAreas(); bool exits_open = true; foreach(pos p in room_exits){ if(!room[p].IsPassable()){ exits_open = false; } } if(exits_open){ for(int i=start_r;i<=end_r;++i){ for(int j=start_c;j<=end_c;++j){ if(list.Contains(new pos(i,j))){ map[i,j] = room[(i-start_r)+1,(j-start_c)+1]; } } } break; } ++tries; if(tries > 50){ return false; } } return true; } default: break; } return true; }); }
/// <summary> /// See if some of the population will convert to a different religion /// Work down pop from oldest to youngest. Pick a random pop, try and convert. /// Atheists don't convert others. /// </summary> public void Conversion() { var t = new List<Population>(population); t.Sort( (a, b) => a.age.CompareTo(b.age) ); t.Reverse(); foreach(var attacker in t) { //Atheists don't convert if(attacker.owner == parent.game.nullGod) continue; var defender = t.Random(); if(attacker.owner == defender.owner) continue; //Attacker roll d6 + age difference. //Wins if greater than defenders age or 6 var attackerBaseRoll = UnityEngine.Random.Range(1, 7); var attackerRoll = attackerBaseRoll + (attacker.age - defender.age); if(attackerBaseRoll == 6 || attackerRoll > defender.age) { defender.owner = attacker.owner; } } }
void ShowDownloadDialog() { statusLabel.GetText = () => "Fetching list of mirrors..."; progressBar.Indeterminate = true; var retryButton = panel.Get<ButtonWidget>("RETRY_BUTTON"); retryButton.IsVisible = () => false; var cancelButton = panel.Get<ButtonWidget>("CANCEL_BUTTON"); var mirrorsFile = Platform.ResolvePath("^", "Content", Game.modData.Manifest.Mod.Id, "mirrors.txt"); var file = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); var dest = Platform.ResolvePath("^", "Content", Game.modData.Manifest.Mod.Id); Action<DownloadProgressChangedEventArgs> onDownloadProgress = i => { var dataReceived = 0.0f; var dataTotal = 0.0f; var mag = 0; var dataSuffix = ""; if (i.TotalBytesToReceive < 0) { dataTotal = float.NaN; dataReceived = i.BytesReceived; dataSuffix = SizeSuffixes[0]; } else { mag = (int)Math.Log(i.TotalBytesToReceive, 1024); dataTotal = i.TotalBytesToReceive / (float)(1L << (mag * 10)); dataReceived = i.BytesReceived / (float)(1L << (mag * 10)); dataSuffix = SizeSuffixes[mag]; } progressBar.Indeterminate = false; progressBar.Percentage = i.ProgressPercentage; statusLabel.GetText = () => "Downloading from {4} {1:0.00}/{2:0.00} {3} ({0}%)".F(i.ProgressPercentage, dataReceived, dataTotal, dataSuffix, mirror != null ? new Uri(mirror).Host : "unknown host"); }; Action<string> onExtractProgress = s => Game.RunAfterTick(() => statusLabel.GetText = () => s); Action<string> onError = s => Game.RunAfterTick(() => { statusLabel.GetText = () => "Error: " + s; retryButton.IsVisible = () => true; }); Action<AsyncCompletedEventArgs, bool> onDownloadComplete = (i, cancelled) => { if (i.Error != null) { onError(Download.FormatErrorMessage(i.Error)); return; } else if (cancelled) { onError("Download cancelled"); return; } // Automatically extract statusLabel.GetText = () => "Extracting..."; progressBar.Indeterminate = true; if (InstallUtils.ExtractZip(file, dest, onExtractProgress, onError)) { Game.RunAfterTick(() => { Ui.CloseWindow(); afterInstall(); }); } }; Action<AsyncCompletedEventArgs, bool> onFetchMirrorsComplete = (i, cancelled) => { progressBar.Indeterminate = true; if (i.Error != null) { onError(Download.FormatErrorMessage(i.Error)); return; } else if (cancelled) { onError("Download cancelled"); return; } var mirrorList = new List<string>(); using (var r = new StreamReader(mirrorsFile)) { string line; while ((line = r.ReadLine()) != null) if (!string.IsNullOrEmpty(line)) mirrorList.Add(line); } mirror = mirrorList.Random(new MersenneTwister()); // Save the package to a temp file var dl = new Download(mirror, file, onDownloadProgress, onDownloadComplete); cancelButton.OnClick = () => { dl.Cancel(); Ui.CloseWindow(); }; retryButton.OnClick = () => { dl.Cancel(); ShowDownloadDialog(); }; }; // Get the list of mirrors var updateMirrors = new Download(mirrorListUrl, mirrorsFile, onDownloadProgress, onFetchMirrorsComplete); cancelButton.OnClick = () => { updateMirrors.Cancel(); Ui.CloseWindow(); }; retryButton.OnClick = () => { updateMirrors.Cancel(); ShowDownloadDialog(); }; }
/// <summary> /// Uses WM, attacking targets. /// </summary> /// <param name="attacker"></param> /// <param name="skill"></param> /// <param name="targetAreaId"></param> /// <param name="unkInt1"></param> /// <param name="unkInt2"></param> public void Use(Creature attacker, Skill skill, long targetAreaId, int unkInt1, int unkInt2) { var range = this.GetRange(attacker, skill); var targets = attacker.GetTargetableCreaturesInRange(range, true); // Check targets if (targets.Count == 0) { Send.Notice(attacker, Localization.Get("There isn't a target nearby to use that on.")); Send.SkillUseSilentCancel(attacker); return; } // Create actions var cap = new CombatActionPack(attacker, skill.Info.Id); var aAction = new AttackerAction(CombatActionType.SpecialHit, attacker, skill.Info.Id, targetAreaId); aAction.Set(AttackerOptions.Result); cap.Add(aAction); var survived = new List<Creature>(); foreach (var target in targets) { target.StopMove(); var tAction = new TargetAction(CombatActionType.TakeHit, target, attacker, skill.Info.Id); tAction.Delay = 300; // Usually 300, sometimes 350? // Calculate damage var damage = attacker.GetRndTotalDamage(); damage *= skill.RankData.Var1 / 100f; // Handle skills and reductions CriticalHit.Handle(attacker, attacker.GetTotalCritChance(0), ref damage, tAction); SkillHelper.HandleDefenseProtection(target, ref damage); Defense.Handle(aAction, tAction, ref damage); ManaShield.Handle(target, ref damage, tAction); // Clean Hit if not defended nor critical if (tAction.SkillId != SkillId.Defense && !tAction.Has(TargetOptions.Critical)) tAction.Set(TargetOptions.CleanHit); // Take damage if any is left if (damage > 0) target.TakeDamage(tAction.Damage = damage, attacker); // Finish if dead, knock down if not defended if (target.IsDead) tAction.Set(TargetOptions.KnockDownFinish); else if (tAction.SkillId != SkillId.Defense) tAction.Set(TargetOptions.KnockDown); // Anger Management if (!target.IsDead) survived.Add(target); // Stun & knock back aAction.Stun = CombatMastery.GetAttackerStun(attacker.AverageKnockCount, attacker.AverageAttackSpeed, true); if (tAction.SkillId != SkillId.Defense) { tAction.Stun = CombatMastery.GetTargetStun(attacker.AverageKnockCount, attacker.AverageAttackSpeed, true); target.Stability = Creature.MinStability; attacker.Shove(target, KnockbackDistance); } // Add action cap.Add(tAction); } // Only select a random aggro if there is no aggro yet, // WM only aggroes one target at a time. if (survived.Count != 0 && attacker.Region.CountAggro(attacker) < 1) { var rnd = RandomProvider.Get(); var aggroTarget = survived.Random(); aggroTarget.Aggro(attacker); } // Reduce life in old combat system if (!AuraData.FeaturesDb.IsEnabled("CombatSystemRenewal")) { var amount = (attacker.LifeMax < 10 ? 2 : attacker.LifeMax / 10); attacker.ModifyLife(-amount); // TODO: Invincibility } // Spin it~ Send.UseMotion(attacker, 8, 4); cap.Handle(); Send.SkillUse(attacker, skill.Info.Id, targetAreaId, unkInt1, unkInt2); skill.Stacks = 0; }
private static void SendContinuousErrors(int delay, CancellationToken token, bool randomizeDates = false, int maxErrors = Int32.MaxValue, int uniqueCount = 1, bool randomizeCritical = true, int maxDaysOld = 90) { _sendingContinuous = true; Console.WriteLine(); Console.WriteLine("Press 's' to stop sending."); int errorCount = 0; if (uniqueCount <= 0) uniqueCount = 1; var errorCodeList = new List<int>(); for (int i = 0; i < uniqueCount; i++) errorCodeList.Add(_random.Next()); Task.Factory.StartNew(delegate { while (errorCount < maxErrors) { if (token.IsCancellationRequested) { _sendingContinuous = false; break; } SendError(randomizeDates, errorCodeList.Random(), randomizeCritical ? RandomHelper.GetBool() : false, writeToConsole: false, maxDaysOld: maxDaysOld); errorCount++; Console.SetCursorPosition(0, 13); Console.WriteLine("Sent {0} errors.", errorCount); Trace.WriteLine(String.Format("Sent {0} errors.", errorCount)); Thread.Sleep(delay); } }, token); }
public static string GenerateScrollName() { //List<string> vowel = new List<string>{"a","e","i","o","u"}; //List<string> consonant = new List<string>{"k","s","t","n","h","m","y","r","w","g","d","p","b"}; //Japanese-inspired - used AEIOU, 4 syllables max, and 3-9 total //List<string> consonant = new List<string>{"h","k","l","n","m","p","w"}; //Hawaiian-inspired //List<string> vowel = new List<string>{"y","i","e","u","ae"}; //some kinda Gaelic-inspired //List<string> consonant = new List<string>{"r","t","s","rr","m","n","w","b","c","d","f","g","l","ss","v"}; //some kinda Gaelic-inspired List<string> vowel = new List<string>{"a","e","i","o","u","ea","ei","io","a","e","i","o","u","a","e","i","o","u","a","e","i","o","oo","ee","a","e","o"}; //the result of a bunch of tweaking List<string> consonant = new List<string>{"k","s","t","n","h","m","y","r","w","g","d","p","b","f","l","v","z","ch","br","cr","dr","fr","gr","kr","pr","tr","th","sc","sh","sk","sl","sm","sn","sp","st","k","s","t","n","m","r","g","d","p","b","l","k","s","t","n","m","r","d","p","b","l",}; int syllables = 0; List<int> syllable_count = null; do{ syllables = R.Roll(4) + 2; syllable_count = new List<int>(); while(syllables > 0){ if(syllable_count.Count == 2){ syllable_count.Add(syllables); syllables = 0; break; } int R2 = Math.Min(syllables,3); int M = 0; if(syllable_count.Count == 0){ //sorry, magic numbers here M = 6; } if(syllable_count.Count == 1){ M = 5; } int D = 0; if(syllable_count.Count == 0){ D = Math.Max(0,syllables - M); } int s = R.Roll(R2 - D) + D; syllable_count.Add(s); syllables -= s; } } while(!syllable_count.Any(x => x!=1)); // if every word has only 1 syllable, try again string result = ""; while(syllable_count.Count > 0){ string word = ""; if(R.OneIn(5)){ word = word + vowel.Random(); } for(int count = syllable_count.RemoveRandom();count > 0;--count){ word = word + consonant.Random() + vowel.Random(); /*if(R.OneIn(20)){ //used for the Japanese-inspired one word = word + "n"; }*/ } if(result == ""){ result = result + word; } else{ result = result + " " + word; } } return result; }
public void OnNudge(Actor self, Actor nudger, bool force) { /* initial fairly braindead implementation. */ if (!force && self.Owner.Stances[nudger.Owner] != Stance.Ally) return; /* don't allow ourselves to be pushed around * by the enemy! */ if (!force && !self.IsIdle) return; /* don't nudge if we're busy doing something! */ // pick an adjacent available cell. var availCells = new List<int2>(); var notStupidCells = new List<int2>(); for (var i = -1; i < 2; i++) for (var j = -1; j < 2; j++) { var p = toCell + new int2(i, j); if (CanEnterCell(p)) availCells.Add(p); else if (p != nudger.Location && p != toCell) notStupidCells.Add(p); } var moveTo = availCells.Any() ? availCells.Random(self.World.SharedRandom) : notStupidCells.Any() ? notStupidCells.Random(self.World.SharedRandom) : (int2?)null; if (moveTo.HasValue) { self.CancelActivity(); self.SetTargetLine(Target.FromCell(moveTo.Value), Color.Green, false); self.QueueActivity(new Move(moveTo.Value, 0)); Log.Write("debug", "OnNudge #{0} from {1} to {2}", self.ActorID, self.Location, moveTo.Value); } else Log.Write("debug", "OnNudge #{0} refuses at {1}", self.ActorID, self.Location); }
public bool Use(Actor user,List<Tile> line) { bool used = true; bool IDed = true; switch(type){ case ConsumableType.HEALING: user.curhp = user.maxhp; B.Add(user.Your() + " wounds are healed completely. ",user); break; case ConsumableType.REGENERATION: { if(user == player){ B.Add("Your blood tingles. "); } else{ B.Add(user.the_name + " looks energized. ",user); } user.attrs[AttrType.REGENERATING]++; int duration = 100; Q.Add(new Event(user,duration*100,AttrType.REGENERATING)); break; } case ConsumableType.STONEFORM: { B.Add(user.You("transform") + " into a being of animated stone. ",user); int duration = R.Roll(2,20) + 20; List<AttrType> attributes = new List<AttrType>{AttrType.REGENERATING,AttrType.BRUTISH_STRENGTH,AttrType.VIGOR,AttrType.SILENCE_AURA,AttrType.SHADOW_CLOAK,AttrType.CAN_DODGE,AttrType.MENTAL_IMMUNITY,AttrType.DETECTING_MONSTERS,AttrType.MYSTIC_MIND}; foreach(AttrType at in attributes){ //in the rare case where a monster drinks this potion, it can lose these natural statuses permanently. this might eventually be fixed. if(user.HasAttr(at)){ user.attrs[at] = 0; Q.KillEvents(user,at); switch(at){ case AttrType.REGENERATING: B.Add(user.You("no longer regenerate") + ". ",user); break; case AttrType.BRUTISH_STRENGTH: B.Add(user.Your() + " brutish strength fades. ",user); break; case AttrType.VIGOR: B.Add(user.Your() + " extraordinary speed fades. ",user); break; case AttrType.SILENCED: B.Add(user.You("no longer radiate") + " an aura of silence. ",user); break; case AttrType.SHADOW_CLOAK: B.Add(user.YouAre() + " no longer cloaked. ",user); break; case AttrType.MYSTIC_MIND: B.Add(user.Your() + " consciousness returns to normal. ",user); break; } } } if(user.HasAttr(AttrType.PSEUDO_VAMPIRIC)){ user.attrs[AttrType.LIGHT_SENSITIVE] = 0; user.attrs[AttrType.FLYING] = 0; user.attrs[AttrType.PSEUDO_VAMPIRIC] = 0; Q.KillEvents(user,AttrType.LIGHT_SENSITIVE); Q.KillEvents(user,AttrType.FLYING); Q.KillEvents(user,AttrType.PSEUDO_VAMPIRIC); B.Add(user.YouAre() + " no longer vampiric. ",user); } if(user.HasAttr(AttrType.ROOTS)){ foreach(Event e in Q.list){ if(e.target == user && !e.dead){ if(e.attr == AttrType.IMMOBILE && e.msg.Contains("rooted to the ground")){ e.dead = true; user.attrs[AttrType.IMMOBILE]--; B.Add(user.YouAre() + " no longer rooted to the ground. ",user); } else{ if(e.attr == AttrType.BONUS_DEFENSE && e.value == 10){ e.dead = true; //this would break if there were other timed effects that gave the same amount of defense user.attrs[AttrType.BONUS_DEFENSE] -= 10; } else{ if(e.attr == AttrType.ROOTS){ e.dead = true; user.attrs[AttrType.ROOTS]--; } } } } } } if(user.HasAttr(AttrType.BURNING)){ user.RefreshDuration(AttrType.BURNING,0); } user.attrs[AttrType.IMMUNE_BURNING]++; Q.Add(new Event(user,duration*100,AttrType.IMMUNE_BURNING)); user.attrs[AttrType.DAMAGE_RESISTANCE]++; Q.Add(new Event(user,duration*100,AttrType.DAMAGE_RESISTANCE)); user.attrs[AttrType.NONLIVING]++; Q.Add(new Event(user,duration*100,AttrType.NONLIVING)); user.RefreshDuration(AttrType.STONEFORM,duration*100,user.Your() + " rocky form reverts to flesh. ",user); if(user == player){ Help.TutorialTip(TutorialTopic.Stoneform); } break; } case ConsumableType.VAMPIRISM: { B.Add(user.You("become") + " vampiric. ",user); B.Add(user.You("rise") + " into the air. ",user); int duration = R.Roll(2,20) + 20; user.RefreshDuration(AttrType.LIGHT_SENSITIVE,duration*100); user.RefreshDuration(AttrType.FLYING,duration*100); user.attrs[AttrType.DESCENDING] = 0; user.RefreshDuration(AttrType.PSEUDO_VAMPIRIC,duration*100,user.YouAre() + " no longer vampiric. ",user); if(user == player){ Help.TutorialTip(TutorialTopic.Vampirism); } break; } case ConsumableType.BRUTISH_STRENGTH: { if(user == player){ B.Add("You feel a surge of strength. "); } else{ B.Add(user.Your() + " muscles ripple. ",user); } user.RefreshDuration(AttrType.BRUTISH_STRENGTH,(R.Roll(3,6)+16)*100,user.Your() + " incredible strength wears off. ",user); if(user == player){ Help.TutorialTip(TutorialTopic.BrutishStrength); } break; } case ConsumableType.ROOTS: { if(user.HasAttr(AttrType.ROOTS)){ foreach(Event e in Q.list){ if(e.target == user && !e.dead){ if(e.attr == AttrType.IMMOBILE && e.msg.Contains("rooted to the ground")){ e.dead = true; user.attrs[AttrType.IMMOBILE]--; } else{ if(e.attr == AttrType.BONUS_DEFENSE && e.value == 10){ e.dead = true; //this would break if there were other timed effects that gave 5 defense user.attrs[AttrType.BONUS_DEFENSE] -= 10; } else{ if(e.attr == AttrType.ROOTS){ e.dead = true; user.attrs[AttrType.ROOTS]--; } } } } } B.Add(user.Your() + " roots extend deeper into the ground. ",user); } else{ B.Add(user.You("grow") + " roots and a hard shell of bark. ",user); } int duration = R.Roll(20) + 20; user.RefreshDuration(AttrType.ROOTS,duration*100); user.attrs[AttrType.BONUS_DEFENSE] += 10; Q.Add(new Event(user,duration*100,AttrType.BONUS_DEFENSE,10)); user.attrs[AttrType.IMMOBILE]++; Q.Add(new Event(user,duration*100,AttrType.IMMOBILE,user.YouAre() + " no longer rooted to the ground. ",user)); if(user == player){ Help.TutorialTip(TutorialTopic.Roots); } if(user.HasAttr(AttrType.FLYING) && user.tile().IsTrap()){ user.tile().TriggerTrap(); } break; } case ConsumableType.HASTE: { B.Add(user.You("start") + " moving with extraordinary speed. ",user); int duration = (R.Roll(2,10) + 10) * 100; user.RefreshDuration(AttrType.CAN_DODGE,duration); //todo: dodging tip goes here user.RefreshDuration(AttrType.VIGOR,duration,user.Your() + " extraordinary speed fades. ",user); if(user == player){ Help.TutorialTip(TutorialTopic.IncreasedSpeed); } break; } case ConsumableType.SILENCE: { B.Add("A hush falls around " + user.the_name + ". ",user); user.RefreshDuration(AttrType.SILENCE_AURA,(R.Roll(2,20)+20)*100,user.You("no longer radiate") + " an aura of silence. ",user); if(user == player){ Help.TutorialTip(TutorialTopic.Silenced); } break; } case ConsumableType.CLOAKING: if(user.tile().IsLit()){ if(user == player){ B.Add("You would feel at home in the shadows. "); } else{ B.Add("A shadow moves across " + user.the_name + ". ",user); } } else{ B.Add(user.You("fade") + " away in the darkness. ",user); } user.RefreshDuration(AttrType.SHADOW_CLOAK,(R.Roll(2,20)+30)*100,user.YouAre() + " no longer cloaked. ",user); break; case ConsumableType.MYSTIC_MIND: { B.Add(user.Your() + " mind expands. ",user); int duration = R.Roll(2,20)+60; user.attrs[AttrType.ASLEEP] = 0; //user.RefreshDuration(AttrType.MAGICAL_DROWSINESS,0); user.RefreshDuration(AttrType.CONFUSED,0); user.RefreshDuration(AttrType.STUNNED,0); user.RefreshDuration(AttrType.ENRAGED,0); user.RefreshDuration(AttrType.MENTAL_IMMUNITY,duration*100); user.RefreshDuration(AttrType.DETECTING_MONSTERS,duration*100); user.RefreshDuration(AttrType.MYSTIC_MIND,duration*100,user.Your() + " consciousness returns to normal. ",user); if(user == player){ Help.TutorialTip(TutorialTopic.MysticMind); } break; } case ConsumableType.BLINKING: { List<Tile> tiles = user.TilesWithinDistance(8).Where(x => x.passable && x.actor() == null && user.ApproximateEuclideanDistanceFromX10(x) >= 45); if(tiles.Count > 0 && !user.HasAttr(AttrType.IMMOBILE)){ Tile t = tiles.Random(); B.Add(user.You("step") + " through a rip in reality. ",M.tile[user.p],t); user.AnimateStorm(2,3,4,'*',Color.DarkMagenta); user.Move(t.row,t.col); M.Draw(); user.AnimateStorm(2,3,4,'*',Color.DarkMagenta); } else{ B.Add("Nothing happens. ",user); IDed = false; } break; } case ConsumableType.PASSAGE: { if(user.HasAttr(AttrType.IMMOBILE)){ B.Add("Nothing happens. ",user); IDed = false; break; } List<int> valid_dirs = new List<int>(); foreach(int dir in U.FourDirections){ Tile t = user.TileInDirection(dir); if(t != null && t.Is(TileType.WALL,TileType.CRACKED_WALL,TileType.WAX_WALL,TileType.DOOR_C,TileType.HIDDEN_DOOR,TileType.STONE_SLAB)){ while(!t.passable){ if(t.row == 0 || t.row == Global.ROWS-1 || t.col == 0 || t.col == Global.COLS-1){ break; } t = t.TileInDirection(dir); } if(t.passable){ valid_dirs.Add(dir); } } } if(valid_dirs.Count > 0){ int dir = valid_dirs.Random(); Tile t = user.TileInDirection(dir); colorchar ch = new colorchar(Color.Cyan,'!'); switch(user.DirectionOf(t)){ case 8: case 2: ch.c = '|'; break; case 4: case 6: ch.c = '-'; break; } List<Tile> tiles = new List<Tile>(); List<colorchar> memlist = new List<colorchar>(); Screen.CursorVisible = false; Tile last_wall = null; while(!t.passable){ tiles.Add(t); memlist.Add(Screen.MapChar(t.row,t.col)); Screen.WriteMapChar(t.row,t.col,ch); Game.GLUpdate(); Thread.Sleep(35); last_wall = t; t = t.TileInDirection(dir); } Input.FlushInput(); if(t.actor() == null){ int r = user.row; int c = user.col; user.Move(t.row,t.col); Screen.WriteMapChar(r,c,M.VisibleColorChar(r,c)); Screen.WriteMapChar(t.row,t.col,M.VisibleColorChar(t.row,t.col)); int idx = 0; foreach(Tile tile in tiles){ Screen.WriteMapChar(tile.row,tile.col,memlist[idx++]); Game.GLUpdate(); Thread.Sleep(35); } Input.FlushInput(); B.Add(user.You("travel") + " through the passage. ",user,t); } else{ Tile destination = null; List<Tile> adjacent = t.TilesAtDistance(1).Where(x=>x.passable && x.actor() == null && x.DistanceFrom(last_wall) == 1); if(adjacent.Count > 0){ destination = adjacent.Random(); } else{ foreach(Tile tile in M.ReachableTilesByDistance(t.row,t.col,false)){ if(tile.actor() == null){ destination = tile; break; } } } if(destination != null){ int r = user.row; int c = user.col; user.Move(destination.row,destination.col); Screen.WriteMapChar(r,c,M.VisibleColorChar(r,c)); Screen.WriteMapChar(destination.row,destination.col,M.VisibleColorChar(destination.row,destination.col)); int idx = 0; foreach(Tile tile in tiles){ Screen.WriteMapChar(tile.row,tile.col,memlist[idx++]); Game.GLUpdate(); Thread.Sleep(35); } Input.FlushInput(); B.Add(user.You("travel") + " through the passage. ",user,destination); } else{ B.Add("Something blocks " + user.Your() + " movement through the passage. ",user); } } } else{ B.Add("Nothing happens. ",user); IDed = false; } break; } case ConsumableType.TIME: if(user == player){ B.Add("Time stops for a moment. ",user); } else{ B.Add("Time warps around " + user.the_name + "! ",user); B.PrintAll(); } if(Fire.fire_event == null){ //this prevents fire from updating while time is frozen Fire.fire_event = new Event(0,EventType.FIRE); Fire.fire_event.tiebreaker = 0; Q.Add(Fire.fire_event); } Q.turn -= 200; break; case ConsumableType.KNOWLEDGE: { if(user == player){ B.Add("Knowledge fills your mind. "); Event hiddencheck = null; foreach(Event e in Q.list){ if(!e.dead && e.type == EventType.CHECK_FOR_HIDDEN){ hiddencheck = e; break; } } int max_dist = 0; List<Tile> last_tiles = new List<Tile>(); foreach(Tile t in M.ReachableTilesByDistance(user.row,user.col,true,TileType.STONE_SLAB,TileType.DOOR_C,TileType.STALAGMITE,TileType.RUBBLE,TileType.HIDDEN_DOOR)){ if(t.type != TileType.FLOOR){ t.seen = true; if(t.type != TileType.WALL){ t.revealed_by_light = true; } if(t.IsTrap() || t.Is(TileType.HIDDEN_DOOR)){ if(hiddencheck != null){ hiddencheck.area.Remove(t); } } if(t.IsTrap()){ t.name = Tile.Prototype(t.type).name; t.a_name = Tile.Prototype(t.type).a_name; t.the_name = Tile.Prototype(t.type).the_name; t.symbol = Tile.Prototype(t.type).symbol; t.color = Tile.Prototype(t.type).color; } if(t.Is(TileType.HIDDEN_DOOR)){ t.Toggle(null); } colorchar ch2 = Screen.BlankChar(); if(t.inv != null){ t.inv.revealed_by_light = true; ch2.c = t.inv.symbol; ch2.color = t.inv.color; M.last_seen[t.row,t.col] = ch2; } else{ if(t.features.Count > 0){ ch2 = t.FeatureVisual(); M.last_seen[t.row,t.col] = ch2; } else{ ch2.c = t.symbol; ch2.color = t.color; if(ch2.c == '#' && ch2.color == Color.RandomGlowingFungus){ ch2.color = Color.Gray; } M.last_seen[t.row,t.col] = ch2; } } Screen.WriteMapChar(t.row,t.col,t.symbol,Color.RandomRainbow); //Screen.WriteMapChar(t.row,t.col,M.VisibleColorChar(t.row,t.col)); if(user.DistanceFrom(t) > max_dist){ max_dist = user.DistanceFrom(t); Game.GLUpdate(); Thread.Sleep(10); while(last_tiles.Count > 0){ Tile t2 = last_tiles.RemoveRandom(); Screen.WriteMapChar(t2.row,t2.col,M.last_seen[t2.row,t2.col]); //Screen.WriteMapChar(t2.row,t2.col,M.VisibleColorChar(t2.row,t2.col)); } } last_tiles.Add(t); } } if(user.inv.Count > 0){ foreach(Item i in user.inv){ identified[i.type] = true; if(i.NameOfItemType() == "wand"){ i.other_data = -1; } } } } else{ B.Add(user.the_name + " looks more knowledgeable. ",user); } break; } case ConsumableType.SUNLIGHT: if(M.wiz_lite == false){ B.Add("The air itself seems to shine. "); M.wiz_lite = true; M.wiz_dark = false; Q.KillEvents(null,EventType.NORMAL_LIGHTING); Q.Add(new Event((R.Roll(2,20) + 120) * 100,EventType.NORMAL_LIGHTING)); } else{ B.Add("The air grows even brighter for a moment. "); Q.KillEvents(null,EventType.NORMAL_LIGHTING); Q.Add(new Event((R.Roll(2,20) + 120) * 100,EventType.NORMAL_LIGHTING)); } break; case ConsumableType.DARKNESS: if(M.wiz_dark == false){ B.Add("The air itself grows dark. "); if(player.light_radius > 0){ B.Add("Your light is extinguished! "); } M.wiz_dark = true; M.wiz_lite = false; Q.KillEvents(null,EventType.NORMAL_LIGHTING); Q.Add(new Event((R.Roll(2,20) + 120) * 100,EventType.NORMAL_LIGHTING)); } else{ B.Add("The air grows even darker for a moment. "); Q.KillEvents(null,EventType.NORMAL_LIGHTING); Q.Add(new Event((R.Roll(2,20) + 120) * 100,EventType.NORMAL_LIGHTING)); } break; case ConsumableType.RENEWAL: { B.Add("A glow envelops " + user.the_name + ". ",user); //B.Add("A glow envelops " + user.Your() + " equipment. ",user); bool repaired = false; foreach(EquipmentStatus eqstatus in Enum.GetValues(typeof(EquipmentStatus))){ foreach(Weapon w in user.weapons){ if(w.status[eqstatus]){ repaired = true; w.status[eqstatus] = false; } } foreach(Armor a in user.armors){ if(a.status[eqstatus]){ repaired = true; a.status[eqstatus] = false; } } } if(repaired){ B.Add(user.Your() + " equipment looks as good as new! ",user); } if(user.HasAttr(AttrType.SLIMED)){ B.Add(user.YouAre() + " no longer covered in slime. ",user); user.attrs[AttrType.SLIMED] = 0; } if(user.HasAttr(AttrType.OIL_COVERED)){ B.Add(user.YouAre() + " no longer covered in oil. ",user); user.attrs[AttrType.OIL_COVERED] = 0; } int recharged = 0; foreach(Item i in user.inv){ if(i.NameOfItemType() == "wand"){ i.charges++; recharged++; } } if(recharged > 0){ if(recharged == 1){ B.Add("The glow charges " + user.Your() + " wand. ",user); } else{ B.Add("The glow charges " + user.Your() + " wands. ",user); } } break; } case ConsumableType.CALLING: { bool found = false; if(user == player){ for(int dist = 1;dist < Math.Max(Global.ROWS,Global.COLS);++dist){ List<Tile> tiles = user.TilesAtDistance(dist).Where(x=>x.actor() != null && !x.actor().HasAttr(AttrType.IMMOBILE)); if(tiles.Count > 0){ Actor a = tiles.Random().actor(); Tile t2 = user.TileInDirection(user.DirectionOf(a)); if(t2.passable && t2.actor() == null){ B.Add("The scroll calls " + a.a_name + " to you. "); a.Move(t2.row,t2.col); found = true; break; } foreach(Tile t in M.ReachableTilesByDistance(user.row,user.col,false)){ if(t.actor() == null){ B.Add("The scroll calls " + a.a_name + " to you. "); a.Move(t.row,t.col); found = true; break; } } if(found){ break; } } } } else{ if(!player.HasAttr(AttrType.IMMOBILE) && user.DistanceFrom(player) > 1){ Tile t2 = user.TileInDirection(user.DirectionOf(player)); if(t2.passable && t2.actor() == null){ B.Add("The scroll calls you to " + user.TheName(true) + ". "); player.Move(t2.row,t2.col); found = true; } if(!found){ foreach(Tile t in M.ReachableTilesByDistance(user.row,user.col,false)){ if(t.actor() == null){ B.Add("The scroll calls you to " + user.TheName(true) + ". "); player.Move(t.row,t.col); found = true; break; } } } } } if(!found){ B.Add("Nothing happens. ",user); IDed = false; } break; } case ConsumableType.TRAP_CLEARING: { List<Tile> traps = new List<Tile>(); { List<Tile>[] traparray = new List<Tile>[5]; for(int i=0;i<5;++i){ traparray[i] = new List<Tile>(); } for(int i=0;i<=12;++i){ foreach(Tile t in user.TilesAtDistance(i)){ //all this ensures that the traps go off in the best order switch(t.type){ case TileType.ALARM_TRAP: case TileType.TELEPORT_TRAP: case TileType.ICE_TRAP: case TileType.BLINDING_TRAP: case TileType.SHOCK_TRAP: case TileType.FIRE_TRAP: case TileType.SCALDING_OIL_TRAP: traparray[0].Add(t); break; case TileType.POISON_GAS_TRAP: case TileType.GRENADE_TRAP: traparray[1].Add(t); break; case TileType.SLIDING_WALL_TRAP: case TileType.PHANTOM_TRAP: traparray[2].Add(t); break; case TileType.LIGHT_TRAP: case TileType.DARKNESS_TRAP: traparray[3].Add(t); break; case TileType.FLING_TRAP: case TileType.STONE_RAIN_TRAP: traparray[4].Add(t); break; } } } for(int i=0;i<5;++i){ foreach(Tile t in traparray[i]){ traps.Add(t); } } } if(traps.Count > 0){ B.Add("*CLICK*. "); foreach(Tile t in traps){ t.TriggerTrap(false); } } else{ B.Add("Nothing happens. ",user); IDed = false; } break; } case ConsumableType.ENCHANTMENT: { if(user == player){ EnchantmentType ench = (EnchantmentType)R.Between(0,4); while(ench == user.EquippedWeapon.enchantment){ ench = (EnchantmentType)R.Between(0,4); } B.Add("Your " + user.EquippedWeapon.NameWithEnchantment() + " glows brightly! "); user.EquippedWeapon.enchantment = ench; B.Add("Your " + user.EquippedWeapon.NameWithoutEnchantment() + " is now a " + user.EquippedWeapon.NameWithEnchantment() + "! "); } else{ B.Add("Nothing happens. ",user); IDed = false; } break; } case ConsumableType.THUNDERCLAP: { B.Add("Thunder crashes! ",user); var scr = Screen.GetCurrentMap(); List<Tile>[] printed = new List<Tile>[13]; Color leading_edge_color = Color.White; Color trail_color = Color.DarkCyan; if(Global.LINUX && !Screen.GLMode){ leading_edge_color = Color.Gray; } for(int dist=0;dist<=12;++dist){ printed[dist] = new List<Tile>(); foreach(Tile t in user.TilesAtDistance(dist)){ if(t.seen && user.HasLOE(t)){ printed[dist].Add(t); } } foreach(Tile t in printed[dist]){ colorchar cch = M.VisibleColorChar(t.row,t.col); cch.bgcolor = leading_edge_color; if(cch.color == leading_edge_color){ cch.color = Color.Black; } Screen.WriteMapChar(t.row,t.col,cch); } if(dist > 0){ foreach(Tile t in printed[dist-1]){ colorchar cch = M.VisibleColorChar(t.row,t.col); cch.bgcolor = trail_color; if(cch.color == trail_color){ cch.color = Color.Black; } Screen.WriteMapChar(t.row,t.col,cch); } if(dist > 4){ foreach(Tile t in printed[dist-5]){ Screen.WriteMapChar(t.row,t.col,scr[t.row,t.col]); } } } Game.GLUpdate(); Thread.Sleep(10); } List<Actor> actors = new List<Actor>(); for(int dist=0;dist<=12;++dist){ foreach(Tile t in user.TilesAtDistance(dist).Randomize()){ if(user.HasLOE(t)){ if(t.actor() != null && t.actor() != user){ actors.Add(t.actor()); } t.BreakFragileFeatures(); } } } foreach(Actor a in actors){ if(a.TakeDamage(DamageType.MAGIC,DamageClass.MAGICAL,R.Roll(4,6),user,"a scroll of thunderclap")){ a.ApplyStatus(AttrType.STUNNED,R.Between(5,10)*100); } } user.MakeNoise(12); break; } case ConsumableType.FIRE_RING: { List<pos> cells = new List<pos>(); List<Tile> valid = new List<Tile>(); foreach(Tile t in user.TilesWithinDistance(3)){ if(t.passable && user.DistanceFrom(t) > 1 && user.HasLOE(t) && user.ApproximateEuclideanDistanceFromX10(t) < 45){ valid.Add(t); cells.Add(t.p); } } if(valid.Count > 0){ if(player.CanSee(user)){ B.Add("A ring of fire surrounds " + user.the_name + ". "); } else{ B.Add("A ring of fire appears! ",user.tile()); } valid.Randomize(); foreach(Tile t in valid){ t.AddFeature(FeatureType.FIRE); } Screen.AnimateMapCells(cells,new colorchar('&',Color.RandomFire)); } else{ B.Add("Nothing happens. ",user); IDed = false; } break; } case ConsumableType.RAGE: { B.Add("A murderous red glow cascades outward. ",user); List<Tile>[] printed = new List<Tile>[13]; Color leading_edge_color = Color.Red; Color trail_color = Color.DarkRed; if(Global.LINUX && !Screen.GLMode){ leading_edge_color = Color.DarkRed; } for(int dist=0;dist<=12;++dist){ printed[dist] = new List<Tile>(); foreach(Tile t in user.TilesAtDistance(dist)){ if(t.seen && user.HasLOS(t)){ printed[dist].Add(t); } } foreach(Tile t in printed[dist]){ colorchar cch = M.VisibleColorChar(t.row,t.col); cch.bgcolor = leading_edge_color; if(cch.color == leading_edge_color){ cch.color = Color.Black; } Screen.WriteMapChar(t.row,t.col,cch); } if(dist > 0){ foreach(Tile t in printed[dist-1]){ colorchar cch = M.VisibleColorChar(t.row,t.col); cch.bgcolor = trail_color; if(cch.color == trail_color){ cch.color = Color.Black; } Screen.WriteMapChar(t.row,t.col,cch); } } Game.GLUpdate(); Thread.Sleep(5); } int actors_affected = 0; string name_is = ""; foreach(Actor a in M.AllActors()){ if(a != user && user.DistanceFrom(a) <= 12 && user.HasLOS(a)){ a.ApplyStatus(AttrType.ENRAGED,R.Between(10,17)*100,false,"",a.You("calm") + " down. ",a.You("resist") + "! "); actors_affected++; if(player.CanSee(a)){ name_is = a.YouAre(); } } } if(actors_affected > 0){ if(actors_affected == 1){ B.Add(name_is + " enraged! "); } else{ B.Add("Bloodlust fills the air. "); } } break; } case ConsumableType.FREEZING: { ItemUseResult orb_result = UseOrb(2,false,user,line,(t,LOE_tile,results)=>{ Screen.AnimateExplosion(t,2,new colorchar('*',Color.RandomIce)); List<Tile> targets = new List<Tile>(); foreach(Tile t2 in t.TilesWithinDistance(2)){ if(LOE_tile.HasLOE(t2)){ targets.Add(t2); } } while(targets.Count > 0){ Tile t2 = targets.RemoveRandom(); t2.ApplyEffect(DamageType.COLD); Actor ac = t2.actor(); if(ac != null){ ac.ApplyFreezing(); } } }); used = orb_result.used; IDed = orb_result.IDed; break; } case ConsumableType.FLAMES: { ItemUseResult orb_result = UseOrb(2,false,user,line,(t,LOE_tile,results)=>{ List<Tile> area = new List<Tile>(); List<pos> cells = new List<pos>(); foreach(Tile tile in t.TilesWithinDistance(2)){ if(LOE_tile.HasLOE(tile)){ if(tile.passable){ tile.AddFeature(FeatureType.FIRE); } else{ tile.ApplyEffect(DamageType.FIRE); } if(tile.Is(FeatureType.FIRE)){ area.Add(tile); } cells.Add(tile.p); } } Screen.AnimateMapCells(cells,new colorchar('&',Color.RandomFire)); }); used = orb_result.used; IDed = orb_result.IDed; break; } case ConsumableType.FOG: { ItemUseResult orb_result = UseOrb(3,false,user,line,(t,LOE_tile,results)=>{ List<Tile> area = new List<Tile>(); List<pos> cells = new List<pos>(); colorchar cch = new colorchar('*',Color.Gray); for(int i=0;i<=3;++i){ foreach(Tile tile in t.TilesAtDistance(i)){ if(tile.passable && LOE_tile.HasLOE(tile)){ tile.AddFeature(FeatureType.FOG); area.Add(tile); cells.Add(tile.p); if(tile.seen){ M.last_seen[tile.row,tile.col] = cch; } } } Screen.AnimateMapCells(cells,cch,40); } Q.RemoveTilesFromEventAreas(area,EventType.REMOVE_GAS); Event.RemoveGas(area,800,FeatureType.FOG,25); //Q.Add(new Event(area,600,EventType.FOG,25)); }); used = orb_result.used; IDed = orb_result.IDed; break; } case ConsumableType.DETONATION: { ItemUseResult orb_result = UseOrb(3,false,user,line,(t,LOE_tile,results)=>{ LOE_tile.ApplyExplosion(3,user,"an orb of detonation"); }); used = orb_result.used; IDed = orb_result.IDed; break; } case ConsumableType.BREACHING: { ItemUseResult orb_result = UseOrb(5,false,user,line,(t,LOE_tile,results)=>{ int max_dist = -1; foreach(Tile t2 in M.TilesByDistance(t.row,t.col,false,true)){ if(t.DistanceFrom(t2) > 5){ break; } if(t2.Is(TileType.WALL,TileType.WAX_WALL,TileType.STALAGMITE,TileType.CRACKED_WALL,TileType.DOOR_C)){ Screen.WriteMapChar(t2.row,t2.col,t2.symbol,Color.RandomBreached); if(t.DistanceFrom(t2) > max_dist){ max_dist = t.DistanceFrom(t2); Game.GLUpdate(); //todo: stalagmites - if I add them to caves, they should no longer always vanish. check for an event, maybe? Thread.Sleep(50); } } } List<Tile> area = new List<Tile>(); foreach(Tile tile in t.TilesWithinDistance(5)){ if(tile.Is(TileType.WALL,TileType.WAX_WALL,TileType.STALAGMITE,TileType.CRACKED_WALL,TileType.DOOR_C) && tile.p.BoundsCheck(M.tile,false)){ TileType prev_type = tile.type; if(tile.Is(TileType.STALAGMITE)){ tile.Toggle(null,TileType.FLOOR); } else{ tile.Toggle(null,TileType.BREACHED_WALL); tile.toggles_into = prev_type; area.Add(tile); } foreach(Tile neighbor in tile.TilesWithinDistance(1)){ neighbor.solid_rock = false; } } } if(area.Count > 0){ Q.Add(new Event(t,area,500,EventType.BREACH)); } }); used = orb_result.used; IDed = orb_result.IDed; break; } case ConsumableType.SHIELDING: { ItemUseResult orb_result = UseOrb(1,true,user,line,(t,LOE_tile,results)=>{ List<Tile> area = new List<Tile>(); List<pos> cells = new List<pos>(); List<colorchar> symbols = new List<colorchar>(); foreach(Tile tile in t.TilesWithinDistance(1)){ if(tile.passable && LOE_tile.HasLOE(tile)){ colorchar cch = tile.visual; if(tile.actor() != null){ if(!tile.actor().HasAttr(AttrType.SHIELDED)){ tile.actor().attrs[AttrType.SHIELDED] = 1; B.Add(tile.actor().YouAre() + " shielded. ",tile.actor()); } if(player.CanSee(tile.actor())){ cch = tile.actor().visual; } } cch.bgcolor = Color.Blue; if(Global.LINUX && !Screen.GLMode){ cch.bgcolor = Color.DarkBlue; } if(cch.color == cch.bgcolor){ cch.color = Color.Black; } if(cch.c == '.'){ cch.c = '+'; } symbols.Add(cch); cells.Add(tile.p); area.Add(tile); } } Screen.AnimateMapCells(cells,symbols,150); foreach(Tile tile in area){ if(player.CanSee(tile)){ B.Add("A zone of protection is created. "); break; } } Q.Add(new Event(area,100,EventType.SHIELDING,R.Roll(2,6)+6)); }); used = orb_result.used; IDed = orb_result.IDed; break; } case ConsumableType.TELEPORTAL: { ItemUseResult orb_result = UseOrb(0,false,user,line,(t,LOE_tile,results)=>{ LOE_tile.AddFeature(FeatureType.TELEPORTAL); if(LOE_tile.Is(FeatureType.TELEPORTAL)){ Q.Add(new Event(LOE_tile,0,EventType.TELEPORTAL,100)); } }); used = orb_result.used; IDed = orb_result.IDed; break; } case ConsumableType.PAIN: { ItemUseResult orb_result = UseOrb(5,false,user,line,(t,LOE_tile,results)=>{ List<pos> cells = new List<pos>(); List<colorchar> symbols = new List<colorchar>(); foreach(Tile tile in t.TilesWithinDistance(5)){ if(LOE_tile.HasLOE(tile)){ Actor a = tile.actor(); if(a != null){ if(a.TakeDamage(DamageType.MAGIC,DamageClass.MAGICAL,R.Roll(2,6),user,"an orb of pain")){ a.ApplyStatus(AttrType.VULNERABLE,(R.Roll(2,6)+6)*100); if(a == player){ Help.TutorialTip(TutorialTopic.Vulnerable); } } } symbols.Add(new colorchar('*',Color.RandomDoom)); /*if(tile.DistanceFrom(t) % 2 == 0){ symbols.Add(new colorchar('*',Color.DarkMagenta)); } else{ symbols.Add(new colorchar('*',Color.DarkRed)); }*/ cells.Add(tile.p); } } player.AnimateVisibleMapCells(cells,symbols,80); }); used = orb_result.used; IDed = orb_result.IDed; break; } case ConsumableType.CONFUSION: { ItemUseResult orb_result = UseOrb(2,false,user,line,(t,LOE_tile,results)=>{ List<Tile> area = new List<Tile>(); List<pos> cells = new List<pos>(); colorchar cch = new colorchar('*',Color.RandomConfusion); for(int i=0;i<=2;++i){ foreach(Tile tile in t.TilesAtDistance(i)){ if(tile.passable && LOE_tile.HasLOE(tile)){ tile.AddFeature(FeatureType.CONFUSION_GAS); area.Add(tile); cells.Add(tile.p); if(tile.seen){ M.last_seen[tile.row,tile.col] = cch; } } } Screen.AnimateMapCells(cells,cch,40); } Q.RemoveTilesFromEventAreas(area,EventType.REMOVE_GAS); Event.RemoveGas(area,R.Between(7,9)*100,FeatureType.CONFUSION_GAS,20); }); used = orb_result.used; IDed = orb_result.IDed; break; } case ConsumableType.BLADES: { ItemUseResult orb_result = UseOrb(1,false,user,line,(t,LOE_tile,results)=>{ List<Tile> targets = new List<Tile>(); foreach(Tile t2 in t.TilesWithinDistance(1)){ if(t2.passable && t2.actor() == null && LOE_tile.HasLOE(t2)){ targets.Add(t2); } } targets.Randomize(); foreach(Tile t2 in targets){ Actor a = Actor.Create(ActorType.BLADE,t2.row,t2.col); if(a != null){ a.speed = 50; } } }); used = orb_result.used; IDed = orb_result.IDed; break; } case ConsumableType.DUST_STORM: { ItemUseResult wand_result = UseWand(true,false,user,line,(LOE_tile,targeting,results)=>{ List<Tile> area = new List<Tile>(); List<pos> cells = new List<pos>(); foreach(Tile neighbor in LOE_tile.TilesWithinDistance(1)){ if(neighbor.passable){ area.Add(neighbor); } } List<Tile> added = new List<Tile>(); foreach(Tile n1 in area){ foreach(int dir in U.FourDirections){ if(R.CoinFlip() && n1.TileInDirection(dir).passable){ added.Add(n1.TileInDirection(dir)); } } } foreach(Tile n1 in added){ area.AddUnique(n1); } colorchar cch = new colorchar('*',Color.TerrainDarkGray); foreach(Tile t2 in area){ t2.AddFeature(FeatureType.THICK_DUST); cells.Add(t2.p); if(t2.seen){ M.last_seen[t2.row,t2.col] = cch; } Actor a = t2.actor(); if(a != null && t2.Is(FeatureType.THICK_DUST)){ if(!a.HasAttr(AttrType.NONLIVING,AttrType.PLANTLIKE,AttrType.BLINDSIGHT)){ if(a == player){ B.Add("Thick dust fills the air! "); } a.ApplyStatus(AttrType.BLIND,R.Between(1,3)*100); } } } Screen.AnimateMapCells(cells,cch,80); Q.RemoveTilesFromEventAreas(area,EventType.REMOVE_GAS); Event.RemoveGas(area,R.Between(20,25)*100,FeatureType.THICK_DUST,8); }); used = wand_result.used; IDed = wand_result.IDed; break; } case ConsumableType.FLESH_TO_FIRE: { ItemUseResult wand_result = UseWand(true,false,user,line,(LOE_tile,targeting,results)=>{ Actor a = targeting.targeted.actor(); if(a != null){ B.Add("Jets of flame erupt from " + a.TheName(true) + ". ",a,targeting.targeted); Screen.AnimateMapCell(a.row,a.col,new colorchar('&',Color.RandomFire)); int dmg = (a.curhp+1)/2; if(a.TakeDamage(DamageType.MAGIC,DamageClass.MAGICAL,dmg,user,"a wand of flesh to fire")){ a.ApplyBurning(); } } else{ if(targeting.targeted.Is(FeatureType.TROLL_CORPSE)){ B.Add("Jets of flame erupt from the troll corpse. ",a,targeting.targeted); targeting.targeted.ApplyEffect(DamageType.FIRE); if(targeting.targeted.Is(FeatureType.TROLL_CORPSE)){ //if it's still there because of thick gas, it still gets destroyed. targeting.targeted.RemoveFeature(FeatureType.TROLL_CORPSE); B.Add("The troll corpse burns to ashes! ",targeting.targeted); } } else{ if(targeting.targeted.Is(FeatureType.TROLL_BLOODWITCH_CORPSE)){ B.Add("Jets of flame erupt from the troll bloodwitch corpse. ",a,targeting.targeted); targeting.targeted.ApplyEffect(DamageType.FIRE); if(targeting.targeted.Is(FeatureType.TROLL_BLOODWITCH_CORPSE)){ //if it's still there because of thick gas, it still gets destroyed. targeting.targeted.RemoveFeature(FeatureType.TROLL_BLOODWITCH_CORPSE); B.Add("The troll bloodwitch corpse burns to ashes! ",targeting.targeted); } } else{ B.Add("Nothing happens. ",user); results.IDed = false; } } } }); used = wand_result.used; IDed = wand_result.IDed; break; } case ConsumableType.INVISIBILITY: { ItemUseResult wand_result = UseWand(false,false,user,line,(LOE_tile,targeting,results)=>{ Actor a = targeting.targeted.actor(); if(a != null){ B.Add(a.You("vanish",true) + " from view. ",a); if(a.light_radius > 0 && !M.wiz_dark && !M.wiz_lite){ B.Add(a.Your() + " light still reveals " + a.Your() + " location. ",a); } a.RefreshDuration(AttrType.INVISIBLE,(R.Between(2,20)+30)*100,a.YouAre() + " no longer invisible. ",a); } else{ B.Add("Nothing happens. ",user); results.IDed = false; } }); used = wand_result.used; IDed = wand_result.IDed; break; } case ConsumableType.REACH: { ItemUseResult wand_result = UseWand(true,false,user,line,(LOE_tile,targeting,results)=>{ Actor a = targeting.targeted.actor(); if(a != null && a != user){ user.Attack(0,a,true); } else{ B.Add("Nothing happens. ",user); results.IDed = false; } }); used = wand_result.used; IDed = wand_result.IDed; break; } case ConsumableType.SLUMBER: { ItemUseResult wand_result = UseWand(true,false,user,line,(LOE_tile,targeting,results)=>{ Actor a = targeting.targeted.actor(); if(a != null){ if(a.HasAttr(AttrType.MENTAL_IMMUNITY)){ if(a.HasAttr(AttrType.NONLIVING,AttrType.PLANTLIKE)){ B.Add(a.You("resist") + " becoming dormant. ",a); } else{ B.Add(a.You("resist") + " falling asleep. ",a); } } else{ if(a.ResistedBySpirit()){ if(player.HasLOS(a)){ if(a.HasAttr(AttrType.NONLIVING,AttrType.PLANTLIKE)){ B.Add(a.You("resist") + " becoming dormant. ",a); } else{ B.Add(a.You("almost fall") + " asleep. ",a); } } } else{ if(player.HasLOS(a)){ if(a.HasAttr(AttrType.NONLIVING,AttrType.PLANTLIKE)){ B.Add(a.You("become") + " dormant. ",a); } else{ B.Add(a.You("fall") + " asleep. ",a); } } a.attrs[AttrType.ASLEEP] = 6 + R.Roll(4,6); } } } else{ B.Add("Nothing happens. ",user); results.IDed = false; } }); used = wand_result.used; IDed = wand_result.IDed; break; } case ConsumableType.TELEKINESIS: { ItemUseResult wand_result = UseWand(true,false,user,line,(LOE_tile,targeting,results)=>{ if(!SharedEffect.Telekinesis(false,user,targeting.targeted)){ results.used = false; } }); used = wand_result.used; IDed = wand_result.IDed; break; } case ConsumableType.WEBS: { ItemUseResult wand_result = UseWand(true,true,user,line,(LOE_tile,targeting,results)=>{ if(targeting.targeted == user.tile()){ B.Add("Nothing happens. ",user); results.IDed = false; } else{ Screen.CursorVisible = false; foreach(Tile t in targeting.line_to_targeted){ if(t.passable && t != user.tile()){ t.AddFeature(FeatureType.WEB); if(t.seen){ Screen.WriteMapChar(t.row,t.col,';',Color.White); Game.GLUpdate(); Thread.Sleep(15); } } } M.Draw(); } }); used = wand_result.used; IDed = wand_result.IDed; break; } case ConsumableType.BLAST_FUNGUS: { if(line == null){ line = user.GetTargetTile(12,0,false,true); } if(line != null){ revealed_by_light = true; ignored = true; Tile t = line.LastBeforeSolidTile(); Actor first = user.FirstActorInLine(line); B.Add(user.You("fling") + " " + TheName() + ". "); if(first != null && first != user){ t = first.tile(); B.Add("It hits " + first.the_name + ". ",first); } line = line.ToFirstSolidTileOrActor(); if(line.Count > 0){ line.RemoveAt(line.Count - 1); } int idx = 0; foreach(Tile tile2 in line){ if(tile2.seen){ ++idx; } else{ line = line.To(tile2); if(line.Count > 0){ line.RemoveAt(line.Count - 1); } break; } } if(line.Count > 0){ user.AnimateProjectile(line,symbol,color); } t.GetItem(this); //inv.Remove(i); t.MakeNoise(2); if(first != null && first != user){ first.player_visibility_duration = -1; first.attrs[AttrType.PLAYER_NOTICED]++; } else{ if(t.IsTrap()){ t.TriggerTrap(); } } } else{ used = false; } break; } case ConsumableType.BANDAGES: if(!user.HasAttr(AttrType.BANDAGED)){ user.attrs[AttrType.BANDAGED] = 20; //user.recover_time = Q.turn + 100; B.Add(user.You("apply",false,true) + " a bandage. ",user); } else{ B.Add(user.the_name + " can't apply another bandage yet. ",user); used = false; } break; case ConsumableType.FLINT_AND_STEEL: { int dir = -1; if(user == player){ dir = user.GetDirection("Which direction? ",false,true); } else{ dir = user.DirectionOf(player); } if(dir != -1){ Tile t = user.TileInDirection(dir); B.Add(user.You("use") + " your flint & steel. ",user); if(t.actor() != null && t.actor().HasAttr(AttrType.OIL_COVERED) && !t.Is(FeatureType.POISON_GAS,FeatureType.THICK_DUST)){ t.actor().ApplyBurning(); } if(!t.Is(TileType.WAX_WALL)){ t.ApplyEffect(DamageType.FIRE); } } else{ used = false; } break; } default: used = false; break; } if(used){ if(IDed){ bool seen = true; //i'll try letting orbs always be IDed. keep an eye on this. /*bool seen = (user == player); if(user != player){ if(player.CanSee(line[0])){ //fix this line - or at least check for null/empty seen = true; } if(user != null && player.CanSee(user)){ //heck, I could even check to see whose turn it is, if I really wanted to be hacky. seen = true; } }*/ if(!identified[type] && seen){ identified[type] = true; B.Add("(It was " + SingularName(true) + "!) "); } } else{ if(!unIDed_name[type].Contains("{tried}")){ unIDed_name[type] = unIDed_name[type] + " {tried}"; } } if(quantity > 1){ --quantity; } else{ if(type == ConsumableType.BANDAGES){ --other_data; if(user != null && other_data == 0){ B.Add(user.You("use") + " your last bandage. ",user); user.inv.Remove(this); } } else{ if(type == ConsumableType.FLINT_AND_STEEL){ if(R.OneIn(3)){ --other_data; if(user != null){ if(other_data == 2){ B.Add("Your flint & steel shows signs of wear. ",user); } if(other_data == 1){ B.Add("Your flint & steel is almost depleted. ",user); } if(other_data == 0){ B.Add("Your flint & steel is used up. ",user); user.inv.Remove(this); } } } } else{ if(NameOfItemType() == "wand"){ if(charges > 0){ --charges; if(other_data >= 0){ ++other_data; } } else{ other_data = -1; } } else{ if(user != null){ user.inv.Remove(this); } } } } } CheckForMimic(); } return used; }