public void FromRuneSet(RuneSet r){ coolDown = 1.5f; if(rID == r.rID)return; rID = r.rID; rune1.GetComponent<Renderer>().material.SetTexture("_MainTex", Runes.GetRuneTexture(r.strg)); rune2.GetComponent<Renderer>().material.SetTexture("_MainTex", Runes.GetRuneTexture(r.stat)); rune3.GetComponent<Renderer>().material.SetTexture("_MainTex", Runes.GetRuneTexture(r.proj)); rune4.GetComponent<Renderer>().material.SetTexture("_MainTex", Runes.GetRuneTexture(r.spec)); }
// todo: consider hashSet.Contains // Number of runes required for set to be complete public static int SetRequired(RuneSet set) { if ((set & RuneSet.Set4) == set) { return(4); } // Not a 4 set => is a 2 set return(2); }
protected override void Remove(bool cancelled) { if (deltas == null) { return; } RuneSet runes = ((Character)Owner).PlayerSpells.Runes; for (RuneType type = RuneType.Blood; type < RuneType.End; ++type) { runes.ModCooldown(type, -deltas[(int)type]); } }
void tBtnRequire_Click(object sender, EventArgs e) { if (setList.SelectedItems.Count == 1) { var li = setList.SelectedItems[0]; RuneSet set = (RuneSet)li.Tag; // whatever, just add it to required if not int num = Build.AddRequiredSet(set); /*if (num > 1) * li.Text = set.ToString() + " x" + num; * if (num > 3 || num <= 1) * li.Text = set.ToString();*/ } }
// Number of runes required for set to be complete public static int SetRequired(RuneSet set) { if (set == RuneSet.Energy || set == RuneSet.Blade || set == RuneSet.Focus || set == RuneSet.Guard || set == RuneSet.Shield || set == RuneSet.Revenge || set == RuneSet.Nemesis || set == RuneSet.Will || set == RuneSet.Endure || set == RuneSet.Destroy) { return(2); } if (set == RuneSet.Swift || set == RuneSet.Fatal || set == RuneSet.Violent || set == RuneSet.Vampire || set == RuneSet.Despair || set == RuneSet.Rage) { return(4); } // Unknown set will never be complete! return(7); }
public static AttributeCategory getSetType(this Rune rune) { var neutral = new RuneSet[] { RuneSet.Violent, RuneSet.Swift, RuneSet.Focus, RuneSet.Nemesis }; if (new RuneSet[] { RuneSet.Fatal, RuneSet.Blade, RuneSet.Rage, RuneSet.Vampire, RuneSet.Revenge }.Contains(rune.Set)) // o { return(AttributeCategory.Offensive); } else if (new RuneSet[] { RuneSet.Energy, RuneSet.Endure, RuneSet.Guard, RuneSet.Shield, RuneSet.Will }.Contains(rune.Set)) // d { return(AttributeCategory.Defensive); } else if (new RuneSet[] { RuneSet.Despair, RuneSet.Determination, RuneSet.Enhance, RuneSet.Fight, RuneSet.Accuracy, RuneSet.Tolerance }.Contains(rune.Set)) // s { return(AttributeCategory.Support); } return(AttributeCategory.Neutral); }
public Rune(long rune_id, long wizard_id, RuneLocation occupied_type, long occupied_id, byte slot_no, RuneColour rank, byte @class, RuneSet set_id, byte upgrade_limit, byte upgrade_curr, int sell_value, List <short> pri_eff, List <short> prefix_eff, List <List <short> > sec_eff, RuneQuality extra) { Id = rune_id; SummonerId = wizard_id; Location = occupied_type; MonsterId = occupied_id; Slot = slot_no; Colour = rank; Stars = @class; Set = set_id; MaxLevel = upgrade_limit; Level = upgrade_curr; SellValue = sell_value; PrimaryStat = new RuneStat(pri_eff); PrefixStat = new RuneStat(prefix_eff); Substats = sec_eff.Select(stat => new RuneStat(stat)).ToList(); Quality = extra; }
public List <MonsterRole> GetByRuneSet(RuneSet runeSet) { return(GetAll().Where(monsterRole => monsterRole.RuneSets.Contains(runeSet)).ToList()); }
public async Task <List <MonsterRole> > GetByRuneSetAsync(RuneSet runeSet) { return(await Task.Run(() => GetByRuneSet(runeSet))); }
public void refresh(string fielpath) { if (fielpath.Length != 0) { //WWW www = new WWW(fielpath); //yield return www; //MemoryStream ms = new MemoryStream(www.bytes); TextAsset txt = Resources.Load(fielpath) as TextAsset; MemoryStream ms = new MemoryStream(txt.bytes); StructArry pbi = Serializer.DeserializeWithLengthPrefix <StructArry>(ms, PrefixStyle.None); Type type = pbi.GetType(); string strname = type.Name; switch (strname) { case "MsgAttackData": MsgAttackData struct1 = pbi as MsgAttackData; DataPool = struct1.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { AttackData dt = DataPool[i] as AttackData; DataStore.Add((int)dt.id, DataPool[i]); } break; case "MsgAwakeningSkill": MsgAwakeningSkill struct2 = pbi as MsgAwakeningSkill; DataPool = struct2.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { AwakeningSkill dt = DataPool[i] as AwakeningSkill; DataStore.Add((int)dt.id, DataPool[i]); } break; case "MsgAwakeningSkillLevel": MsgAwakeningSkillLevel struct3 = pbi as MsgAwakeningSkillLevel; DataPool = struct3.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { AwakeningSkillLevel dt = DataPool[i] as AwakeningSkillLevel; DataStore.Add((int)dt.id, DataPool[i]); } break; case "MsgElementFactor": MsgElementFactor struct4 = pbi as MsgElementFactor; DataPool = struct4.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { ElementFactor dt = DataPool[i] as ElementFactor; DataStore.Add((int)dt.id, DataPool[i]); } break; case "MsgBuffData": MsgBuffData struct5 = pbi as MsgBuffData; DataPool = struct5.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { BuffData dt = DataPool[i] as BuffData; DataStore.Add((int)dt.id, DataPool[i]); } break; case "MsgCombinationData": MsgCombinationData struct6 = pbi as MsgCombinationData; DataPool = struct6.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { CombinationData dt = DataPool[i] as CombinationData; DataStore.Add((int)dt.id, DataPool[i]); } break; case "MsgConstData": MsgConstData struct7 = pbi as MsgConstData; DataPool = struct7.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { ConstData dt = DataPool[i] as ConstData; DataStore.Add((int)dt.id, DataPool[i]); } break; case "MsgCurrency": MsgCurrency struct8 = pbi as MsgCurrency; DataPool = struct8.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { Currency dt = DataPool[i] as Currency; DataStore.Add((int)dt.id, DataPool[i]); } break; case "MsgDungeon": MsgDungeon struct9 = pbi as MsgDungeon; DataPool = struct9.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { Dungeon dt = DataPool[i] as Dungeon; DataStore.Add((int)dt.id, DataPool[i]); } break; case "MsgEnemyData": MsgEnemyData struct10 = pbi as MsgEnemyData; DataPool = struct10.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { EnemyData dt = DataPool[i] as EnemyData; DataStore.Add((int)dt.id, DataPool[i]); } break; case "MsgEvaluateBonus": MsgEvaluateBonus struct11 = pbi as MsgEvaluateBonus; DataPool = struct11.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { EvaluateBonus dt = DataPool[i] as EvaluateBonus; DataStore.Add((int)dt.id, DataPool[i]); } break; case "MsgFieldEffect": MsgFieldEffect struct12 = pbi as MsgFieldEffect; DataPool = struct12.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { FieldEffect dt = DataPool[i] as FieldEffect; DataStore.Add((int)dt.id, DataPool[i]); } break; case "MsgHeroData": MsgHeroData struct13 = pbi as MsgHeroData; DataPool = struct13.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { HeroData dt = DataPool[i] as HeroData; DataStore.Add((int)dt.id, DataPool[i]); } break; case "MsgHeroLvData": MsgHeroLvData struct14 = pbi as MsgHeroLvData; DataPool = struct14.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { HeroLvData dt = DataPool[i] as HeroLvData; DataStore.Add((int)dt.level, DataPool[i]); } break; case "MsgHeroEvolution": MsgHeroEvolution struct15 = pbi as MsgHeroEvolution; DataPool = struct15.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { HeroEvolution dt = DataPool[i] as HeroEvolution; DataStore.Add((int)dt.id, DataPool[i]); } break; case "MsgPotentialData": MsgPotentialData struct16 = pbi as MsgPotentialData; DataPool = struct16.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { PotentialData dt = DataPool[i] as PotentialData; DataStore.Add((int)dt.element, DataPool[i]); } break; case "MsgItemData": MsgItemData struct17 = pbi as MsgItemData; DataPool = struct17.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { ItemData dt = DataPool[i] as ItemData; DataStore.Add((int)dt.id, DataPool[i]); } break; case "MsgLeaderSkill": MsgLeaderSkill struct18 = pbi as MsgLeaderSkill; DataPool = struct18.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { LeaderSkill dt = DataPool[i] as LeaderSkill; DataStore.Add((int)dt.id, DataPool[i]); } break; case "MsgMonsterData": MsgMonsterData struct19 = pbi as MsgMonsterData; DataPool = struct19.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { MonsterData dt = DataPool[i] as MonsterData; DataStore.Add((int)dt.id, DataPool[i]); } break; case "MsgMonsterSkill": MsgMonsterSkill struct20 = pbi as MsgMonsterSkill; DataPool = struct20.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { MonsterSkill dt = DataPool[i] as MonsterSkill; DataStore.Add((int)dt.id, DataPool[i]); } break; case "MsgNormalSkill": MsgNormalSkill struct21 = pbi as MsgNormalSkill; DataPool = struct21.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { NormalSkill dt = DataPool[i] as NormalSkill; DataStore.Add((int)dt.id, DataPool[i]); } break; case "MsgNormalSkillLvUp": MsgNormalSkillLvUp struct22 = pbi as MsgNormalSkillLvUp; DataPool = struct22.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { NormalSkillLvUp dt = DataPool[i] as NormalSkillLvUp; DataStore.Add((int)dt.id, DataPool[i]); } break; case "MsgRoleData": MsgRoleData struct23 = pbi as MsgRoleData; DataPool = struct23.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { RoleData dt = DataPool[i] as RoleData; DataStore.Add((int)dt.level, DataPool[i]); } break; case "MsgRuneData": MsgRuneData struct24 = pbi as MsgRuneData; DataPool = struct24.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { RuneData dt = DataPool[i] as RuneData; DataStore.Add((int)dt.id, DataPool[i]); } break; case "MsgRuneSet": MsgRuneSet struct25 = pbi as MsgRuneSet; DataPool = struct25.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { RuneSet dt = DataPool[i] as RuneSet; DataStore.Add((int)dt.id, DataPool[i]); } break; case "MsgRuneEnhance": MsgRuneEnhance struct26 = pbi as MsgRuneEnhance; DataPool = struct26.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { RuneEnhance dt = DataPool[i] as RuneEnhance; DataStore.Add((int)dt.level, DataPool[i]); } break; case "MsgRuneSynchro": MsgRuneSynchro struct27 = pbi as MsgRuneSynchro; DataPool = struct27.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { RuneSynchro dt = DataPool[i] as RuneSynchro; DataStore.Add((int)dt.id, DataPool[i]); } break; case "MsgSpecialSkill": MsgSpecialSkill struct28 = pbi as MsgSpecialSkill; DataPool = struct28.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { SpecialSkill dt = DataPool[i] as SpecialSkill; DataStore.Add((int)dt.id, DataPool[i]); } break; case "MsgSpecialSkillLvUp": MsgSpecialSkillLvUp struct29 = pbi as MsgSpecialSkillLvUp; DataPool = struct29.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { SpecialSkillLvUp dt = DataPool[i] as SpecialSkillLvUp; DataStore.Add((int)dt.id, DataPool[i]); } break; case "MsgDecisionFactor": MsgDecisionFactor struct30 = pbi as MsgDecisionFactor; DataPool = struct30.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { DecisionFactor dt = DataPool[i] as DecisionFactor; DataStore.Add((int)dt.id, DataPool[i]); } break; case "MsgTaskData": MsgTaskData struct31 = pbi as MsgTaskData; DataPool = struct31.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { TaskData dt = DataPool[i] as TaskData; DataStore.Add((int)dt.id, DataPool[i]); } break; case "MsgHeroText": MsgHeroText struct32 = pbi as MsgHeroText; DataPool = struct32.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { HeroText dt = DataPool[i] as HeroText; Util.TextDic.Add(Util.GetConfigString(dt.name), Util.GetConfigString(dt.textDes)); } break; case "MsgDungeonText": MsgDungeonText struct33 = pbi as MsgDungeonText; DataPool = struct33.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { DungeonText dt = DataPool[i] as DungeonText; Util.TextDic.Add(Util.GetConfigString(dt.name), Util.GetConfigString(dt.textDes)); } break; case "MsgMonsterText": MsgMonsterText struct34 = pbi as MsgMonsterText; DataPool = struct34.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { MonsterText dt = DataPool[i] as MonsterText; Util.TextDic.Add(Util.GetConfigString(dt.name), Util.GetConfigString(dt.textDes)); } break; case "MsgFieldText": MsgFieldText struct35 = pbi as MsgFieldText; DataPool = struct35.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { FieldText dt = DataPool[i] as FieldText; Util.TextDic.Add(Util.GetConfigString(dt.name), Util.GetConfigString(dt.textDes)); } break; case "MsgCombinationText": MsgCombinationText struct36 = pbi as MsgCombinationText; DataPool = struct36.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { CombinationText dt = DataPool[i] as CombinationText; Util.TextDic.Add(Util.GetConfigString(dt.name), Util.GetConfigString(dt.textDes)); } break; case "MsgSkillText": MsgSkillText struct37 = pbi as MsgSkillText; DataPool = struct37.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { SkillText dt = DataPool[i] as SkillText; Util.TextDic.Add(Util.GetConfigString(dt.name), Util.GetConfigString(dt.textDes)); } break; case "MsgCurrencyText": MsgCurrencyText struct38 = pbi as MsgCurrencyText; DataPool = struct38.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { CurrencyText dt = DataPool[i] as CurrencyText; Util.TextDic.Add(Util.GetConfigString(dt.name), Util.GetConfigString(dt.textDes)); } break; case "MsgBuffText": MsgBuffText struct39 = pbi as MsgBuffText; DataPool = struct39.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { BuffText dt = DataPool[i] as BuffText; Util.TextDic.Add(Util.GetConfigString(dt.name), Util.GetConfigString(dt.textDes)); } break; case "MsgItemText": MsgItemText struct40 = pbi as MsgItemText; DataPool = struct40.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { ItemText dt = DataPool[i] as ItemText; Util.TextDic.Add(Util.GetConfigString(dt.name), Util.GetConfigString(dt.textDes)); } break; case "MsgRuneText": MsgRuneText struct41 = pbi as MsgRuneText; DataPool = struct41.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { RuneText dt = DataPool[i] as RuneText; Util.TextDic.Add(Util.GetConfigString(dt.name), Util.GetConfigString(dt.textDes)); } break; case "MsgTaskText": MsgTaskText struct42 = pbi as MsgTaskText; DataPool = struct42.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { TaskText dt = DataPool[i] as TaskText; Util.TextDic.Add(Util.GetConfigString(dt.name), Util.GetConfigString(dt.textDes)); } break; case "MsgWorldData": MsgWorldData struct43 = pbi as MsgWorldData; DataPool = struct43.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { WorldData dt = DataPool[i] as WorldData; DataStore.Add((int)dt.id, DataPool[i]); } break; case "MsgAirRaidData": MsgAirRaidData struct44 = pbi as MsgAirRaidData; DataPool = struct44.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { AirRaidData dt = DataPool[i] as AirRaidData; DataStore.Add((int)dt.id, DataPool[i]); } break; case "MsgTalentData": MsgTalentData struct45 = pbi as MsgTalentData; DataPool = struct45.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { TalentData dt = DataPool[i] as TalentData; DataStore.Add((int)dt.id, DataPool[i]); } break; case "MsgSummonData": MsgSummonData struct46 = pbi as MsgSummonData; DataPool = struct46.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { SummonData dt = DataPool[i] as SummonData; DataStore.Add((int)dt.id, DataPool[i]); } break; case "MsgSummonPrize": MsgSummonPrize struct47 = pbi as MsgSummonPrize; DataPool = struct47.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { SummonPrize dt = DataPool[i] as SummonPrize; DataStore.Add((int)dt.id, DataPool[i]); } break; case "MsgStarWeight": MsgStarWeight struct48 = pbi as MsgStarWeight; DataPool = struct48.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { StarWeight dt = DataPool[i] as StarWeight; DataStore.Add((int)dt.id, DataPool[i]); } break; case "MsgSpecialEffect": MsgSpecialEffect struct49 = pbi as MsgSpecialEffect; DataPool = struct49.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { SpecialEffect dt = DataPool[i] as SpecialEffect; DataStore.Add((int)dt.id, DataPool[i]); } break; case "MsgFlyingEffect": MsgFlyingEffect struct50 = pbi as MsgFlyingEffect; DataPool = struct50.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { FlyingEffect dt = DataPool[i] as FlyingEffect; DataStore.Add((int)dt.id, DataPool[i]); } break; case "MsgDistanceFactor": MsgDistanceFactor struct51 = pbi as MsgDistanceFactor; DataPool = struct51.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { DistanceFactor dt = DataPool[i] as DistanceFactor; DataStore.Add((int)dt.id, DataPool[i]); } break; case "MsgEvaluateData": MsgEvaluateData struct52 = pbi as MsgEvaluateData; DataPool = struct52.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { EvaluateData dt = DataPool[i] as EvaluateData; DataStore.Add((int)dt.id, DataPool[i]); } break; case "MsgPromptText": MsgPromptText struct53 = pbi as MsgPromptText; DataPool = struct53.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { PromptText dt = DataPool[i] as PromptText; Util.TextDic.Add(Util.GetConfigString(dt.name), Util.GetConfigString(dt.textDes)); } break; case "MsgStoryText": MsgStoryText struct54 = pbi as MsgStoryText; DataPool = struct54.struct_data as List <Struct>; for (int i = 0; i < DataPool.Count; i++) { StoryText dt = DataPool[i] as StoryText; Util.TextDic.Add(Util.GetConfigString(dt.name), Util.GetConfigString(dt.textDes)); } break; } } }
// Check what sets are completed in this build public void CheckSets() { SetsFull = false; // If there are an odd number of runes, don't bother (maybe even check < 6?) if (runeCount % 2 == 1) { return; } // can only have 3 sets max (eg. energy / energy / blade) sets = new RuneSet[3]; // which set we are looking for int setInd = 0; // what slot we are looking at int slotInd = 0; // if we have used this slot in a set yet bool[] used = new bool[6]; // how many runes are in sets int setNums = 0; // Check slots 1 - 5, minimum set size is 2. // Because it will search forward for sets, can't find more from 6 // Eg. starting from 6, working around, find 2 runes? for (; slotInd < 5; slotInd++) { //if there is a uncounted rune in this slot Rune rune = runes[slotInd]; if (rune != null && used[slotInd] == false) { // look for more in the set RuneSet set = rune.Set; // how many runes we need to get int getNum = Rune.SetRequired(set); // how many we got int gotNum = 1; // we have now used this slot used[slotInd] = true; // for the runes after this rune for (int ind = slotInd + 1; ind < 6; ind++) { // if there is a rune in this slot if (runes[ind] != null) { // that hasn't been counted if (used[ind] == false) { // that is the type I want if (runes[ind].Set == set) { used[ind] = true; gotNum++; } } } // if we have more than 1 rune if (gotNum > 1) { // if we have enough runes for a set if (gotNum == getNum) { // log this set sets[setInd] = set; // increase the number of runes in sets setNums += getNum; // look for the next set setInd++; // stop looking forward break; } } } } } // if all runes are in sets if (setNums == 6) { SetsFull = true; } // notify hackers their attempt has failed else if (setNums > 6) { throw new Exception("Wut"); } }
public BuildResult GenBuilds(string prefix = "") { if (Type == BuildType.Lock) { Best = new Monster(Mon, true); return BuildResult.Success; } else if (Type == BuildType.Link) { if (LinkBuild == null) { for (int i = 0; i < 6; i++) runes[i] = new Rune[0]; return BuildResult.Failure; } else { CopyFrom(LinkBuild); } } if (runes.Any(r => r == null)) { BuildPrintTo?.Invoke(this, PrintToEventArgs.GetEvent(this, "Null rune")); return BuildResult.BadRune; } if (!BuildSaveStats) BuildGoodRunes = false; if (!BuildGoodRunes) { RuneUsage = new RuneUsage(); BuildUsage = new BuildUsage(); } try { // if to get awakened if (DownloadAwake && !Mon.downloaded) { BuildPrintTo?.Invoke(this, PrintToEventArgs.GetEvent(this, "Downloading Awake def")); var mref = MonsterStat.FindMon(Mon); if (mref != null) { // download the current (unawakened monster) var mstat = mref.Download(); BuildPrintTo?.Invoke(this, PrintToEventArgs.GetEvent(this, "Reading stats")); // if the retrieved mon is unawakened, get the awakened if (!mstat.Awakened && mstat.AwakenTo != null) { BuildPrintTo?.Invoke(this, PrintToEventArgs.GetEvent(this, "Awakening")); Mon = mstat.AwakenTo.Download().GetMon(Mon); } } BuildPrintTo?.Invoke(this, PrintToEventArgs.GetEvent(this, "Downloaded")); } // getting awakened also gets level 40, so... // only get lvl 40 stats if the monster isn't 40, wants to download AND isn't already downloaded (first and last are about the same) else if (Mon.level < 40 && DownloadStats && !Mon.downloaded) { BuildPrintTo?.Invoke(this, PrintToEventArgs.GetEvent(this, "Downloading 40 def")); var mref = MonsterStat.FindMon(Mon); if (mref != null) Mon = mref.Download().GetMon(Mon); } } catch (Exception e) { BuildPrintTo?.Invoke(this, PrintToEventArgs.GetEvent(this, "Failed downloading def: " + e.Message + Environment.NewLine + e.StackTrace)); } if (!getRunningHandle()) throw new InvalidOperationException("The build is locked with another action."); Loads.Clear(); if (!Sort[Attr.Speed].EqualTo(0) && Sort[Attr.Speed] <= 1 // 1 SPD is too good to pass || Mon.Current.Runes.Any(r => r == null) || !Mon.Current.Runes.All(r => runes[r.Slot - 1].Contains(r)) // only IgnoreLess5 if I have my own runes || Sort.NonZeroStats.HasCount(1)) // if there is only 1 sorting, must be too important to drop??? IgnoreLess5 = false; Thread timeThread = null; if (!string.IsNullOrWhiteSpace(BuildStrategy)) { var types = AppDomain.CurrentDomain.GetAssemblies().SelectMany(asm => asm.GetTypes().Where(t => typeof(IBuildStrategyDefinition).IsAssignableFrom(t))); var type = types.FirstOrDefault(t => t.AssemblyQualifiedName.Contains(BuildStrategy)); if (type != null) { RunStrategy(); } } tcs.TrySetResult(null); try { Best = null; Stats bstats = null; count = 0; actual = 0; total = runes[0].Length; total *= runes[1].Length; total *= runes[2].Length; total *= runes[3].Length; total *= runes[4].Length; total *= runes[5].Length; complete = total; Mon.ExtraCritRate = extraCritRate; Mon.GetStats(); Mon.DamageFormula?.Invoke(Mon); int?[] slotFakesTemp = new int?[6]; bool[] slotPred = new bool[6]; getPrediction(slotFakesTemp, slotPred); int[] slotFakes = slotFakesTemp.Select(i => i ?? 0).ToArray(); var currentLoad = new Monster(Mon, true); currentLoad.Current.TempLoad = true; currentLoad.Current.Buffs = Buffs; currentLoad.Current.Shrines = Shrines; currentLoad.Current.Leader = Leader; currentLoad.Current.FakeLevel = slotFakes; currentLoad.Current.PredictSubs = slotPred; double currentScore = CalcScore(currentLoad.GetStats(true)); BuildPrintTo?.Invoke(this, PrintToEventArgs.GetEvent(this, "cooking")); if (total == 0) { BuildPrintTo?.Invoke(this, PrintToEventArgs.GetEvent(this, "0 perms")); RuneLog.Info("Zero permuations"); return BuildResult.NoPermutations; } bool hasSort = Sort.IsNonZero; if (BuildTake == 0 && !hasSort) { BuildPrintTo?.Invoke(this, PrintToEventArgs.GetEvent(this, "No sort")); RuneLog.Info("No method of determining best"); return BuildResult.NoSorting; } DateTime begin = DateTime.Now; RuneLog.Debug(count + "/" + total + " " + string.Format("{0:P2}", (count + complete - total) / (double)complete)); // set to running IsRunning = true; #if BUILD_PRECHECK_BUILDS_DEBUG SynchronizedCollection<string> outstrs = new SynchronizedCollection<string>(); #endif BuildPrintTo?.Invoke(this, PrintToEventArgs.GetEvent(this, "...")); List<Monster> tests = new List<Monster>(); timeThread = new Thread(() => { while (IsRunning) { if (RunesOnlyFillEmpty) Thread.Sleep(30 / ((Mon?.Current?.RuneCount ?? 1) + 1)); else Thread.Sleep(400); // every second, give a bit of feedback to those watching RuneLog.Debug(count + "/" + total + " " + string.Format("{0:P2}", (count + complete - total) / (double)complete)); if (tests != null) BuildProgTo?.Invoke(this, ProgToEventArgs.GetEvent(this, (count + complete - total) / (double)complete, tests.Count)); if (BuildTimeout > 0 && DateTime.Now > begin.AddSeconds(BuildTimeout)) { RuneLog.Info("Timeout"); BuildPrintTo?.Invoke(this, PrintToEventArgs.GetEvent(this, prefix + "Timeout")); BuildProgTo?.Invoke(this, ProgToEventArgs.GetEvent(this, 1, tests.Count)); IsRunning = false; } } }); timeThread.Start(); double bestScore = double.MinValue; var opts = new ParallelOptions() { MaxDegreeOfParallelism = Environment.ProcessorCount - 1 }; var mmm = Maximum.NonZeroCached; // Parallel the outer loop // TODO: setup the begin/finish Actions with syncList. void body (Rune r0, ParallelLoopState loopState) { var tempReq = RequiredSets.ToList(); var tempMax = Maximum == null || !Maximum.IsNonZero ? null : new Stats(Maximum, true); int tempCheck = 0; Monster myBest = null; List<Monster> syncList = new List<Monster>(); void syncMyList() { lock (bestLock) { #if DEBUG_SYNC_BUILDS foreach (var s in syncList) { if (s.Current.Runes.All(r => r.Assigned == mon)) { Console.WriteLine("!"); } } #endif tests.AddRange(syncList); } //syncList.ForEach(_ => tests.Add(_)); syncList.Clear(); if (tests.Count > Math.Max(BuildGenerate, 250000)) { #if DEBUG_SYNC_BUILDS var rems = tests.OrderByDescending(b => b.score).Skip(75000).ToList(); foreach (var bbb in rems) { if (bbb.Current.Runes.All(r => r.Assigned == mon)) { Console.WriteLine("!"); } } #endif lock (bestLock) { tests = tests.OrderByDescending(b => b.score).Take(75000).ToList(); } } if (tests.Count > MaxBuilds32) IsRunning = false; } if (!IsRunning_Unsafe) { syncMyList(); loopState.Break(); } // number of builds ruled out since last sync int kill = 0; // number of builds added since last sync int plus = 0; // number of builds skipped int skip = 0; bool isBad; double myBestScore = double.MinValue, curScore, lastBest = double.MinValue; Stats cstats, myStats; Monster test = new Monster(Mon); test.Current.TempLoad = true; test.Current.Buffs = Buffs; test.Current.Shrines = Shrines; test.Current.Leader = Leader; test.Current.FakeLevel = slotFakes; test.Current.PredictSubs = slotPred; test.ApplyRune(r0, 7); RuneSet set4 = r0.SetIs4 ? r0.Set : RuneSet.Null; RuneSet set2 = r0.SetIs4 ? RuneSet.Null : r0.Set; int pop4 = 0; int pop2 = 0; foreach (Rune r1 in runes[1]) { // TODO: refactor to local method if (!IsRunning_Unsafe) // Can't break to a label, don't want to goto break; // TODO: break into multiple implementations that have less branching #if BUILD_PRECHECK_BUILDS if (!AllowBroken && !RunesOnlyFillEmpty) { if (r1.SetIs4) { if (pop2 == 2) pop2 = 7; if (set4 == RuneSet.Null || pop4 >= 2) { set4 = r1.Set; pop4 = 2; } else if (set4 != r1.Set) { #if BUILD_PRECHECK_BUILDS_DEBUG outstrs.Add($"bad4@2 {set4} {set2} | {r0.Set} {r1.Set}"); #endif skip += runes[2].Length * runes[3].Length * runes[4].Length * runes[5].Length; continue; } } else { if (pop4 == 2) pop4 = 7; if (set2 == RuneSet.Null || pop2 >= 2) { set2 = r1.Set; pop2 = 2; } } } #endif test.ApplyRune(r1, 7); foreach (Rune r2 in runes[2]) { if (!IsRunning_Unsafe) break; #if BUILD_PRECHECK_BUILDS if (!AllowBroken && !RunesOnlyFillEmpty) { if (r2.SetIs4) { if (pop2 == 3) pop2 = 7; if (set4 == RuneSet.Null || pop4 >= 3) { set4 = r2.Set; pop4 = 3; } else if (set4 != r2.Set) { #if BUILD_PRECHECK_BUILDS_DEBUG outstrs.Add($"bad4@3 {set4} {set2} | {r0.Set} {r1.Set} {r2.Set}"); #endif skip += runes[3].Length * runes[4].Length * runes[5].Length; continue; } } else { if (pop4 == 3) pop4 = 7; if (set2 == RuneSet.Null || pop2 >= 3) { set2 = r2.Set; pop2 = 3; } else if (set4 != RuneSet.Null && set2 != r2.Set) { #if BUILD_PRECHECK_BUILDS_DEBUG outstrs.Add($"bad2@3 {set4} {set2} | {r0.Set} {r1.Set} {r2.Set}"); #endif skip += runes[3].Length * runes[4].Length * runes[5].Length; continue; } } } #endif test.ApplyRune(r2, 7); foreach (Rune r3 in runes[3]) { if (!IsRunning_Unsafe) break; #if BUILD_PRECHECK_BUILDS if (!AllowBroken && !RunesOnlyFillEmpty) { if (r3.SetIs4) { if (pop2 == 4) pop2 = 7; if (set4 == RuneSet.Null || pop4 >= 4) { set4 = r3.Set; pop4 = 4; } else if (set4 != r3.Set) { #if BUILD_PRECHECK_BUILDS_DEBUG outstrs.Add($"bad4@4 {set4} {set2} | {r0.Set} {r1.Set} {r2.Set} {r3.Set}"); #endif skip += runes[4].Length * runes[5].Length; continue; } } else { if (pop4 == 4) pop4 = 7; if (set2 == RuneSet.Null || pop2 >= 4) { set2 = r3.Set; pop2 = 4; } else if (set4 != RuneSet.Null && set2 != r3.Set) { #if BUILD_PRECHECK_BUILDS_DEBUG outstrs.Add($"bad2@4 {set4} {set2} | {r0.Set} {r1.Set} {r2.Set} {r3.Set}"); #endif skip += runes[4].Length * runes[5].Length; continue; } } } #endif test.ApplyRune(r3, 7); foreach (Rune r4 in runes[4]) { if (!IsRunning_Unsafe) { break; } #if BUILD_PRECHECK_BUILDS if (!AllowBroken && !RunesOnlyFillEmpty) { if (r4.SetIs4) { if (pop2 == 5) pop2 = 7; if (set4 == RuneSet.Null || pop4 >= 5) { set4 = r4.Set; pop4 = 5; } else if (set4 != r4.Set) { #if BUILD_PRECHECK_BUILDS_DEBUG outstrs.Add($"bad4@5 {set4} {set2} | {r0.Set} {r1.Set} {r2.Set} {r3.Set} {r4.Set}"); #endif skip += runes[5].Length; continue; } } else { if (pop4 == 5) pop4 = 7; if (set2 == RuneSet.Null || pop2 >= 5) { set2 = r4.Set; pop2 = 5; } else if (set4 != RuneSet.Null && set2 != r4.Set) { #if BUILD_PRECHECK_BUILDS_DEBUG outstrs.Add($"bad2@5 {set4} {set2} | {r0.Set} {r1.Set} {r2.Set} {r3.Set} {r4.Set}"); #endif skip += runes[5].Length; continue; } } } #endif test.ApplyRune(r4, 7); foreach (Rune r5 in runes[5]) { if (!IsRunning_Unsafe) break; test.ApplyRune(r5, 7); test.Current.CheckSets(); #if BUILD_PRECHECK_BUILDS_DEBUG outstrs.Add($"fine {set4} {set2} | {r0.Set} {r1.Set} {r2.Set} {r3.Set} {r4.Set} {r5.Set}"); #endif isBad = false; cstats = test.GetStats(); // check if build meets minimum isBad |= !RunesOnlyFillEmpty && !AllowBroken && !test.Current.SetsFull; isBad |= tempMax != null && cstats.AnyExceedCached(tempMax); if (!isBad && GrindLoads) { var mahGrinds = grinds.ToList(); for (int rg = 0; rg < 6; rg++) { var lgrinds = test.Runes[rg].FilterGrinds(mahGrinds); foreach (var g in lgrinds) { var tr = test.Runes[rg].Grind(g); } // TODO: } } isBad |= !RunesOnlyFillEmpty && Minimum != null && !cstats.GreaterEqual(Minimum, true); // if no broken sets, check for broken sets // if there are required sets, ensure we have them /*isBad |= (tempReq != null && tempReq.Count > 0 // this Linq adds no overhead compared to GetStats() and ApplyRune() //&& !tempReq.All(s => test.Current.Sets.Count(q => q == s) >= tempReq.Count(q => q == s)) //&& !tempReq.GroupBy(s => s).All(s => test.Current.Sets.Count(q => q == s.Key) >= s.Count()) );*/ // TODO: recheck this code is correct if (tempReq != null && tempReq.Count > 0) { tempCheck = 0; foreach (var r in tempReq) { int i; for (i = 0; i < 3; i++) { if (test.Current.Sets[i] == r && (tempCheck & 1 << i) != 1 << i) { tempCheck |= 1 << i; break; } } if (i >= 3) { isBad |= true; break; } } } if (isBad) { kill++; curScore = 0; } else { // try to reduce CalcScore hits curScore = CalcScore(cstats); isBad |= IgnoreLess5 && curScore < currentScore * 1.05; if (isBad) kill++; } if (!isBad) { // we found an okay build! plus++; test.score = curScore; if (BuildSaveStats) { foreach (Rune r in test.Current.Runes) { if (!BuildGoodRunes) { r.manageStats.AddOrUpdate("LoadFilt", 1, (s, d) => { return d + 1; }); RuneUsage.runesGood.AddOrUpdate(r, (byte)r.Slot, (key, ov) => (byte)r.Slot); r.manageStats.AddOrUpdate("currentBuildPoints", curScore, (k, v) => Math.Max(v, curScore)); r.manageStats.AddOrUpdate("cbp" + ID, curScore, (k, v) => Math.Max(v, curScore)); } else { r.manageStats.AddOrUpdate("LoadFilt", 0.001, (s, d) => { return d + 0.001; }); RuneUsage.runesOkay.AddOrUpdate(r, (byte)r.Slot, (key, ov) => (byte)r.Slot); r.manageStats.AddOrUpdate("cbp" + ID, curScore, (k, v) => Math.Max(v, curScore * 0.9)); } } } if (syncList.Count >= 500) { syncMyList(); } // if we are to track all good builds, keep it if (!BuildDumpBads) { syncList.Add(new Monster(test, true)); // locally track my best if (myBest == null || curScore > myBestScore) { myBest = new Monster(test, true); myStats = myBest.GetStats(); myBestScore = CalcScore(myStats); myBest.score = myBestScore; } // if mine is better than what I last saw if (myBestScore > lastBest) { lock (bestLock) { if (Best == null) { Best = new Monster(myBest, true); bstats = Best.GetStats(); bestScore = CalcScore(bstats); Best.score = bestScore; } else { // sync best score lastBest = bestScore; // double check if (myBestScore > lastBest) { Best = new Monster(myBest, true); bestScore = CalcScore(bstats); Best.score = bestScore; bstats = Best.GetStats(); } } } } } // if we only want to track really good builds else { // if there are currently no good builds, keep it // or if this build is better than the best, keep it // locally track my best if (myBest == null || curScore > myBestScore) { myBest = new Monster(test, true); myStats = myBest.GetStats(); myBestScore = CalcScore(myStats); myBest.score = myBestScore; syncList.Add(myBest); } else if (BuildSaveStats) { // keep it for spreadsheeting syncList.Add(new Monster(test, true) { score = curScore }); } } } } // sum up what work we've done Interlocked.Add(ref count, kill); Interlocked.Add(ref count, skip); Interlocked.Add(ref skipped, skip); Interlocked.Add(ref actual, kill); Interlocked.Add(ref BuildUsage.failed, kill); kill = 0; skip = 0; Interlocked.Add(ref count, plus); Interlocked.Add(ref actual, plus); Interlocked.Add(ref BuildUsage.passed, plus); plus = 0; // if we've got enough, stop if (BuildGenerate > 0 && BuildUsage.passed >= BuildGenerate) { IsRunning = false; break; } } } } } // just before dying syncMyList(); } Parallel.ForEach(runes[0], opts, body); BuildPrintTo?.Invoke(this, PrintToEventArgs.GetEvent(this, prefix + "finalizing...")); BuildProgTo?.Invoke(this, ProgToEventArgs.GetEvent(this, 0.99, -1)); #if BUILD_PRECHECK_BUILDS_DEBUG System.IO.File.WriteAllLines("_into_the_bridge.txt", outstrs.ToArray()); #endif if (BuildSaveStats) { foreach (var ra in runes) { foreach (var r in ra) { if (!BuildGoodRunes) { r.manageStats.AddOrUpdate("buildScoreTotal", CalcScore(Best), (k, v) => v + CalcScore(Best)); RuneUsage.runesUsed.AddOrUpdate(r, (byte)r.Slot, (key, ov) => (byte)r.Slot); r.manageStats.AddOrUpdate("LoadGen", total, (s, d) => { return d + total; }); } else { RuneUsage.runesBetter.AddOrUpdate(r, (byte)r.Slot, (key, ov) => (byte)r.Slot); r.manageStats.AddOrUpdate("LoadGen", total * 0.001, (s, d) => { return d + total * 0.001; }); } } } } // write out completion RuneLog.Debug(IsRunning + " " + count + "/" + total + " " + string.Format("{0:P2}", (count + complete - total) / (double)complete)); BuildPrintTo?.Invoke(this, PrintToEventArgs.GetEvent(this, prefix + " completed")); BuildProgTo?.Invoke(this, ProgToEventArgs.GetEvent(this, 1, tests.Count)); // sort *all* the builds int takeAmount = 1; if (BuildSaveStats) takeAmount = 10; if (BuildTake > 0) takeAmount = BuildTake; if (IgnoreLess5) tests.Add(new Monster(Mon, true)); foreach (var ll in tests.Where(t => t != null).OrderByDescending(r => CalcScore(r.GetStats())).Take(takeAmount)) Loads.Add(ll); BuildPrintTo?.Invoke(this, PrintToEventArgs.GetEvent(this, "Found a load " + Loads.Count())); if (!BuildGoodRunes) BuildUsage.loads = tests.ToList(); // dump everything to console, if nothing to print to if (BuildPrintTo == null) foreach (var l in Loads) { RuneLog.Debug(l.GetStats().Health + " " + l.GetStats().Attack + " " + l.GetStats().Defense + " " + l.GetStats().Speed + " " + l.GetStats().CritRate + "%" + " " + l.GetStats().CritDamage + "%" + " " + l.GetStats().Resistance + "%" + " " + l.GetStats().Accuracy + "%"); } // sadface if no builds if (!Loads.Any()) { RuneLog.Info("No builds :("); BuildPrintTo?.Invoke(this, PrintToEventArgs.GetEvent(this, prefix + "Zero :(")); } else { // remember the good one Best = Loads.First(); Best.Current.TempLoad = false; Best.score = CalcScore(Best.GetStats()); BuildPrintTo?.Invoke(this, PrintToEventArgs.GetEvent(this, prefix + "best " + (Best?.score ?? -1))); Best.Current.ActualTests = actual; foreach (var bb in Loads) { foreach (Rune r in bb.Current.Runes) { double val = Best.score; if (BuildGoodRunes) { val *= 0.25; if (bb == Best) RuneUsage.runesSecond.AddOrUpdate(r, (byte)r.Slot, (key, ov) => (byte)r.Slot); } if (bb != Best) val *= 0.1; else r.manageStats.AddOrUpdate("In", BuildGoodRunes ? 2 : 1, (s, e) => BuildGoodRunes ? 2 : 1); r.manageStats.AddOrUpdate("buildScoreIn", val, (k, v) => v + val); } } for (int i = 0; i < 6; i++) { if (!BuildGoodRunes && Mon.Current.Runes[i] != null && Mon.Current.Runes[i].Id != Best.Current.Runes[i].Id) Mon.Current.Runes[i].Swapped = true; } foreach (var ra in runes) { foreach (var r in ra) { var cbp = r.manageStats.GetOrAdd("currentBuildPoints", 0); if (cbp / Best.score < 1) r.manageStats.AddOrUpdate("bestBuildPercent", cbp / Best.score, (k, v) => Math.Max(v, cbp / Best.score)); } } } tests.Clear(); tests = null; BuildPrintTo?.Invoke(this, PrintToEventArgs.GetEvent(this, prefix + "Test cleared")); return BuildResult.Success; } catch (Exception e) { RuneLog.Error("Error " + e); BuildPrintTo?.Invoke(this, PrintToEventArgs.GetEvent(this, prefix + e.ToString())); return BuildResult.Failure; } finally { tcs = new TaskCompletionSource<IBuildRunner>(); IsRunning = false; if (timeThread != null) timeThread.Join(); } }
public static IEnumerable<Rune>[] MakeSets(IList<Rune> runes, Attr slot2, Attr slot4, Attr slot6, Predicate<Rune> odds, RuneSet[] reqsets = null) { Rune[][] runesSlot = new Rune[6][]; Predicate<Rune> set = r => true; if (reqsets != null) { int reqCount = 0; foreach (RuneSet s in reqsets) reqCount += Rune.SetRequired(s); if (reqCount == 6) set = r => reqsets.Any(s => s == r.Set); } var unlocked = runes.Where(r => !r.Locked).ToArray(); var sets = unlocked.Where(r => set.Invoke(r)).ToArray(); var odd = sets.Where(r => odds.Invoke(r)).ToArray(); runesSlot[0] = odd.Where(r => r.Slot == 1).ToArray(); runesSlot[1] = sets.Where(r => r.Slot == 2 && (r.MainType == slot2 || slot2 == Attr.Null)).ToArray(); runesSlot[2] = odd.Where(r => r.Slot == 3).ToArray(); runesSlot[3] = sets.Where(r => r.Slot == 4 && (r.MainType == slot4 || slot4 == Attr.Null)).ToArray(); runesSlot[4] = odd.Where(r => r.Slot == 5).ToArray(); runesSlot[5] = sets.Where(r => r.Slot == 6 && (r.MainType == slot6 || slot6 == Attr.Null)).ToArray(); foreach (Rune[] rs in runesSlot.Where(r => r.Length == 0)) Console.WriteLine("No runes for slot " + (runesSlot.ToList().IndexOf(rs) + 1) + ":("); return runesSlot; }
public static IEnumerable<Rune>[] MakeSets(IList<Rune> runes, Predicate<Rune> evens, Predicate<Rune> odds, RuneSet[] reqsets = null) { IEnumerable<Rune>[] runesSlot = new IEnumerable<Rune>[6]; Predicate<Rune> set = r => true; if (reqsets != null) { int reqCount = 0; foreach (RuneSet s in reqsets) reqCount += Rune.SetRequired(s); if (reqCount == 6) set = r => reqsets.Any(s => s == r.Set); } runesSlot[0] = runes.Where(r => r.Slot == 1 && !r.Locked && odds.Invoke(r) && set.Invoke(r)); runesSlot[1] = runes.Where(r => r.Slot == 2 && !r.Locked && evens.Invoke(r) && set.Invoke(r)); runesSlot[2] = runes.Where(r => r.Slot == 3 && !r.Locked && odds.Invoke(r) && set.Invoke(r)); runesSlot[3] = runes.Where(r => r.Slot == 4 && !r.Locked && evens.Invoke(r) && set.Invoke(r)); runesSlot[4] = runes.Where(r => r.Slot == 5 && !r.Locked && odds.Invoke(r) && set.Invoke(r)); runesSlot[5] = runes.Where(r => r.Slot == 6 && !r.Locked && evens.Invoke(r) && set.Invoke(r)); return runesSlot; }
public Rune(Rune rhs) { ID = rhs.ID; Set = rhs.Set; Grade = rhs.Grade; Slot = rhs.Slot; Level = rhs.Level; //FakeLevel = rhs.FakeLevel; //PredictSubs = rhs.PredictSubs; Locked = rhs.Locked; AssignedId = rhs.AssignedId; AssignedName = rhs.AssignedName; Assigned = rhs.Assigned; Swapped = rhs.Swapped; MainType = rhs.MainType; MainValue = rhs.MainValue; InnateType = rhs.InnateType; InnateValue = rhs.InnateValue; Sub1Type = rhs.Sub1Type; Sub1Value = rhs.Sub1Value; Sub2Type = rhs.Sub2Type; Sub2Value = rhs.Sub2Value; Sub3Type = rhs.Sub3Type; Sub3Value = rhs.Sub3Value; Sub4Type = rhs.Sub4Type; Sub4Value = rhs.Sub4Value; Parent = rhs; }
public void FromRuneSet(RuneSet r){ string stat = Runes.RUNE_NAME[r.stat]; string spec = Runes.RUNE_NAME[r.spec]; feNumProjectiles = r.proj/10f; feFire = 0; feStun = 0; feFreeze = 0; if(stat == "Accignar"){ feFire = Mathf.Max(0.4f,Random.value); }else if(stat == "Adtomar"){ feStun = Mathf.Max(0.4f,Random.value); } feMana = Random.value; feAcceleration = Random.value; feLifetime = Mathf.Max(0.55f, Random.value); feSpread = Mathf.Max(0.6f, Random.value); feVelocity = Mathf.Max(0.4f,Random.value); feHoming = 0; fePiercing = 0; feChaining = 0; if(spec == "Traicatur"){ fePiercing = Mathf.Max(0.4f, Random.value); }else if(spec == "Reqconur"){ //feHoming = Mathf.Max(0.4f, Random.value); } feDamage = Mathf.Max(0.4f, Random.value); fvRed = Random.value; fvGreen = Random.value; fvBlue = Random.value; if(stat == "Accignar"){ fvRed = Mathf.Max(0.6f, Random.value); fvGreen = Mathf.Min(0.3f, Random.value); fvBlue = Mathf.Min(0.3f, Random.value); }else if(stat == "Adtomar"){ fvRed = Mathf.Min(0.7f, Random.value); fvGreen = fvRed; fvBlue = Mathf.Max(0.8f, Random.value); } fvSize = Mathf.Max(0.1f,Random.value); fvTrail = Mathf.Max(0.3f,Random.value); fvFade = Random.value; }
// Number of runes required for set to be complete public static int SetRequired(RuneSet set) { if (set == RuneSet.Energy || set == RuneSet.Blade || set == RuneSet.Focus || set == RuneSet.Guard || set == RuneSet.Shield || set == RuneSet.Revenge || set == RuneSet.Nemesis || set == RuneSet.Will || set == RuneSet.Endure || set == RuneSet.Destroy) return 2; if (set == RuneSet.Swift || set == RuneSet.Fatal || set == RuneSet.Violent || set == RuneSet.Vampire || set == RuneSet.Despair || set == RuneSet.Rage) return 4; // Unknown set will never be complete! return 7; }
/*// NYI comparison public EquipCompare CompareTo(Loadout rhs) { // check if the sets are comparable if (CompareSets(sets, rhs.sets) == 0) return EquipCompare.Unknown; int side = 0; if (HealthPercent > rhs.HealthPercent) side++; else side--; if (AttackPercent > rhs.AttackPercent) side++; else side--; if (DefensePercent > rhs.DefensePercent) side++; else side--; if (Speed > rhs.Speed) return EquipCompare.Unknown; } */ // TODO: return an enum? // NYI comparison // 0 = differing magical sets // 1 = exact match // 2 = none or no differing magic sets public static int CompareSets(RuneSet[] a, RuneSet[] b) { if (a == b) return 1; if (a.Length == b.Length) { int same = 0; for (int i = 0; i < a.Length; i++) { if (a[i] == b[i]) same++; } if (same == a.Length) return 1; } // different lengths, or not the same sets // count the number of magical sets, and make sure both loadout have the same number of sets foreach (RuneSet s in Rune.MagicalSets) { if (a.Where(x => x == s).Count() != b.Where(x => x == s).Count()) return 0; } return 1; }