// initial setup / referential setup void InitiateVertices() { legacyVertices = new Dictionary <ProceduralObject, Dictionary <Vertex, KeyValuePair <Vector3, Vector3> > >(); foreach (var obj in selection) { if (obj.isRootOfGroup && logic.selectedGroup == null) { foreach (var o in obj.group.objects) { var dict = new Dictionary <Vertex, KeyValuePair <Vector3, Vector3> >(); foreach (Vertex v in o.vertices) { dict.Add(v, new KeyValuePair <Vector3, Vector3>(ProceduralUtils.VertexWorldPosition(v, o), Vector3.zero)); } legacyVertices.Add(o, dict); } } else { var dict = new Dictionary <Vertex, KeyValuePair <Vector3, Vector3> >(); foreach (Vertex v in obj.vertices) { dict.Add(v, new KeyValuePair <Vector3, Vector3>(ProceduralUtils.VertexWorldPosition(v, obj), Vector3.zero)); } legacyVertices.Add(obj, dict); } } }
static private CardDescription GenerateTrapCard(System.Random random, IHistogram model, ImageGlossary images, CreatureModelIndex creatureModels, NameModel nameModel, CardGenerationFlags flags) { CardDescription card = ScriptableObject.CreateInstance(typeof(CardDescription)) as CardDescription; card.cardType = CardType.TRAP; card.manaCost = (int)ProceduralUtils.GetRandomValue <ManaCost>(random, model); double powerBudget = PowerBudget.ManaPowerBudgets[card.manaCost]; double powerMargin = PowerBudget.ManaPowerMargin[card.manaCost]; double powerLimit = PowerBudget.ManaPowerLimit[card.manaCost]; card.cardName = "A trap card"; //card.name += "(" + powerBudget.ToString() + ")"; GenerateCardEffects(random, model, creatureModels, card, powerBudget, powerMargin, powerLimit); // Revise the mana cost based on what effects we actually did generate int revisedMana = PowerBudget.PowerLevelToMana(card.PowerLevel()); if (revisedMana != card.manaCost) { Debug.Log("Had to revise the mana cost from " + card.manaCost.ToString() + " to " + revisedMana.ToString()); card.manaCost = revisedMana; } card.image = ProceduralUtils.GetRandomTexture(random, images.GetTrapImages()); CardTags tags = CardTagging.GetCardTags(card); card.cardName = nameModel.GenerateName(random, tags); return(card); }
public override ITargettingDescription Generate() { ExceptTargetDescription desc = new ExceptTargetDescription(targetType, alignment); TargettingType exceptTargetting = TargettingType.TARGET; switch (desc.GetPlayerAlignment()) { case Alignment.POSITIVE: exceptTargetting = TargettingType.TARGET_ALLY; break; case Alignment.NEGATIVE: exceptTargetting = TargettingType.TARGET_ENEMY; break; } IProceduralTargettingGenerator targetGen = ProceduralUtils.GetProceduralGenerator(exceptTargetting); targetGen.SetupParameters(targetType, random, model, minAllocatedBudget, maxAllocatedBudget); desc.targetDescription = targetGen.Generate(); if (desc.targetDescription is IQualifiableTargettingDescription qualifiableDesc) { qualifiableDesc.qualifier = desc.qualifier; } return(desc); }
public override IEffectDescription Generate() { DrawEffectDescription desc = new DrawEffectDescription(); desc.drawModifier = ProceduralUtils.GetRandomValue <DrawModifier>(random, model); // Find the bounds of card amounts int max = ProceduralUtils.GetUpperBound(desc, ref desc.amount, MIN_CARDS, MAX_CARDS, maxAllocatedBudget); int min = ProceduralUtils.GetLowerBound(desc, ref desc.amount, MIN_CARDS, max, minAllocatedBudget); Assert.IsTrue(max >= min); desc.amount = random.Next(min, max); // Attempt to narrow down the qualifier pool SortedSet <QualifierType> allowableQualifiers = CardEnums.GetValidFlags <QualifierType>(EffectType.DRAW_CARDS); QualifierType qualifier = ProceduralUtils.GetRandomValue(random, model, allowableQualifiers); if (qualifier != QualifierType.NONE) { IProceduralQualifierGenerator qualifierGen = ProceduralUtils.GetProceduralGenerator(qualifier); qualifierGen.SetupParameters(random, model, minAllocatedBudget / desc.PowerLevel(), maxAllocatedBudget / desc.PowerLevel()); desc.cardQualifier = qualifierGen.Generate(); } return(desc); }
public void Edit(ProceduralObject obj, Vector2 position) { editingObject = obj; scrollParams = Vector2.zero; scrollTex = Vector2.zero; movingField = -1; dragTexPos = Vector2.zero; windowRect.position = position; Texture tex = ProceduralUtils.GetOriginalTexture(obj); originalTex = new Texture2D(tex.width, tex.height, TextureFormat.RGBA32, false); originalTex.SetPixels(((Texture2D)tex).GetPixels()); windowTex = (Texture2D)GameObject.Instantiate(originalTex); // load stored data if it exists if (editingObject.m_textParameters == null) { parameters = new TextParameters(); parametersOld = new TextParameters(); } else { parameters = editingObject.m_textParameters; parametersOld = TextParameters.Clone(editingObject.m_textParameters, false); windowTex = parameters.ApplyParameters(originalTex); editingObject.m_material.mainTexture = windowTex as Texture; } updateTimer = 0f; dragTimer = 0f; zoomFactor = 1f; if (!showWindow) { showWindow = true; } }
public override IQualifierDescription Generate() { CardTypeQualifierDescription desc = new CardTypeQualifierDescription(); desc.cardType = ProceduralUtils.GetRandomValue <CardType>(random, model); return(desc); }
public override IModifierDescription Generate() { KeywordModifierDescription desc = new KeywordModifierDescription(); desc.keyword = ProceduralUtils.GetRandomValueExcluding(random, model, new KeywordAttribute[] { KeywordAttribute.NONE }); return(desc); }
protected override void UpdateTerrainData(float[,] data) { if (mat != null) { mat.mainTexture = ProceduralUtils.GenerateTexture2D(data); mat.mainTexture.filterMode = FilterMode.Point; mat.mainTexture.wrapMode = TextureWrapMode.Clamp; } }
private void MoveChildrenObj(float dt) { if (!groupFollows || !parentObject.isRootOfGroup) { return; } if (parentObject.group == null) { return; } if (dt == -1f) //initialize "points","vys" (children -> position,Y-speed) { points.Clear(); vys.Clear(); foreach (var child in parentObject.group.objects.Where(p => p != parentObject)) { points.Add(child.m_position); vys.Add(initialSpeed.y); } } else if (dt == -2f) //reset "points" (children -> position) { int i = 0; foreach (var child in parentObject.group.objects.Where(p => p != parentObject)) { child.m_position = new Vector3(points[i].x, points[i].y, points[i].z); i++; } } else if (dt == -3f) //reset "vys" (children -> Y-speed) { int i = 0; foreach (var child in parentObject.group.objects.Where(p => p != parentObject)) { vys[i] = initialSpeed.y; i++; } } else //update "child.m_position","vys" { int i = 0; foreach (var child in parentObject.group.objects.Where(p => p != parentObject)) { vys[i] = vys[i] - gravity * dt; child.m_position = new Vector3( child.m_position.x + dt * initialSpeed.x, child.m_position.y + dt * vys[i], child.m_position.z + dt * initialSpeed.z); if (child.m_position.y < ProceduralUtils.NearestGroundPointVertical(child.m_position).y) { child.m_position.y = child.m_position.y - dt * vys[i]; vys[i] = -vys[i] * bounceFactor; } i++; } } }
void RecenterAllOrigins() { foreach (var PODictPair in legacyVertices) { var po = PODictPair.Key; ProceduralUtils.RecenterObjOrigin(po, po.vertices); po.ApplyModelChange(); } }
public override IModifierDescription Generate() { ManaCostModifierDescription desc = new ManaCostModifierDescription(positive); int max = ProceduralUtils.GetUpperBound(desc, ref desc.manaCost, MIN_STATS, MAX_STATS, maxAllocatedBudget); int min = ProceduralUtils.GetLowerBound(desc, ref desc.manaCost, MIN_STATS, MAX_STATS, minAllocatedBudget); desc.manaCost = random.Next(min, max + 1); return(desc); }
private string GetShowName() { if (pickerPrefabNames.Count == 1) { return(ProceduralUtils.GetDisplayableAssetname(pickerPrefabNames[0])); } else { return(string.Format(LocalizationManager.instance.current["filters_pickertypes"], pickerPrefabNames.Count.ToString())); } }
public override IEffectDescription Generate() { DamageEffectDescription desc = new DamageEffectDescription(heal); // Find the bounds of damage amounds int max = ProceduralUtils.GetUpperBound(desc, ref desc.amount, MIN_DAMAGE, MAX_DAMAGE, maxAllocatedBudget); int min = ProceduralUtils.GetLowerBound(desc, ref desc.amount, MIN_DAMAGE, max, minAllocatedBudget); Assert.IsTrue(max >= min); desc.amount = random.Next(min, max + 1); return(desc); }
public override ITargettingDescription Generate() { TargetXDescription desc = new TargetXDescription(targetType, alignment); // Find the bounds of card amounts int max = ProceduralUtils.GetUpperBound(desc, ref desc.amount, MinTargets(), MaxTargets(), maxAllocatedBudget); int min = ProceduralUtils.GetLowerBound(desc, ref desc.amount, MinTargets(), max, minAllocatedBudget); Assert.IsTrue(max >= min); desc.amount = random.Next(min, max); return(desc); }
public override IEffectDescription Generate() { SummonEffectDescription desc = new SummonEffectDescription(); desc.tokenType = ProceduralUtils.GetRandomValue <CreatureType>(random, model); desc.manaCost = creatureModelIndex.GetToken(desc.tokenType).manaCost; // Find the bounds of card amounts int max = ProceduralUtils.GetUpperBound(desc, ref desc.amount, MIN_SUMMONS, MAX_SUMMONS, maxAllocatedBudget); int min = ProceduralUtils.GetLowerBound(desc, ref desc.amount, MIN_SUMMONS, max, minAllocatedBudget); Assert.IsTrue(max >= min); desc.amount = random.Next(min, max); return(desc); }
void CalculateProjection() { foreach (var obj in selection) { if (obj.isRootOfGroup && logic.selectedGroup == null) { // when root of group var bounds = obj.m_mesh.bounds; foreach (var po in obj.group.objects) { // this should eventually take into account the global bounds of the group, not only itself, // so as to project groups as structured units, not each individual PO var vertexDict = legacyAndProjectedVertices[po]; foreach (Vertex v in po.vertices) { var old = vertexDict[v].Key; var projected = ProjectPoint(ProceduralUtils.VertexWorldPosition(old, po), projectionDirection); projected = Quaternion.Inverse(po.m_rotation) * (projected - po.m_position); if (offset != 0f) { projected -= (projected - old).normalized * offset; } vertexDict[v] = new KeyValuePair <Vector3, Vector3>(old, projected); } } } else { // when inside group / not root of group var bounds = obj.m_mesh.bounds; var vertexDict = legacyAndProjectedVertices[obj]; foreach (Vertex v in obj.vertices) { var old = vertexDict[v].Key; var projected = ProjectPoint(ProceduralUtils.VertexWorldPosition(old, obj), projectionDirection); projected = Quaternion.Inverse(obj.m_rotation) * (projected - obj.m_position); if (offset != 0f) { projected -= (projected - old).normalized * offset; } vertexDict[v] = new KeyValuePair <Vector3, Vector3>(old, projected); } } } }
Vector3 ProjectPoint(Vector3 worldPoint, Vector3 worldDirection) { bool hasTerrainHit = false; Vector3 terrainHit; worldPoint = worldPoint - (worldDirection * 3f); if (ProceduralUtils.TryRaycastTerrain(worldPoint, worldDirection, out terrainHit, collideNetworksBuildings)) { hasTerrainHit = true; } RaycastHit physicsHit; if (Physics.Raycast(new Ray(worldPoint, worldDirection), out physicsHit, 2000)) { if (physicsHit.collider.gameObject.name.StartsWith("PO_ColliderProject")) { var point = physicsHit.point; if (hasTerrainHit) { if ((point - worldPoint).sqrMagnitude < (terrainHit - worldPoint).sqrMagnitude) { return(point); } else { return(terrainHit); } } else { return(point); } } } if (hasTerrainHit) { return(terrainHit); } else { return(worldPoint); } }
public override IModifierDescription Generate() { StatModifierDescription desc = new StatModifierDescription(positive); int singleMax = ProceduralUtils.GetUpperBound(desc, ref desc.atk, MIN_STATS, MAX_STATS, maxAllocatedBudget); int singleMin = ProceduralUtils.GetLowerBound(desc, ref desc.atk, MIN_STATS, MAX_STATS, minAllocatedBudget); int doubleMax = ProceduralUtils.GetUpperBound(desc, ref desc.atk, ref desc.def, MIN_STATS, MAX_STATS, maxAllocatedBudget); int doubleMin = ProceduralUtils.GetLowerBound(desc, ref desc.atk, ref desc.def, MIN_STATS, MAX_STATS, minAllocatedBudget); bool single = random.NextDouble() > 0.5; bool atk = random.NextDouble() > 0.5; if (!single && singleMax == 1) { single = true; } else if (single && doubleMin * 2 > singleMax) { single = false; } if (single) { int value = random.Next(singleMin, singleMax + 1); if (atk) { desc.atk = value; } else { desc.def = value; } } else { int value = random.Next(doubleMin, doubleMax + 1); desc.atk = value; desc.def = value; } return(desc); }
public void Apply() { foreach (var obj in selection) { obj.customTexture = tex; var texture = (tex == null) ? ProceduralUtils.GetBasePrefabMainTex(obj) : tex; obj.m_material.mainTexture = texture; if (obj.m_textParameters != null) { if (obj.m_textParameters.Count() > 0) { Texture original = ProceduralUtils.GetOriginalTexture(obj); var originalTex = new Texture2D(original.width, original.height, TextureFormat.RGBA32, false); originalTex.SetPixels(((Texture2D)original).GetPixels()); var newtex = (Texture2D)GameObject.Instantiate(originalTex); obj.m_material.mainTexture = obj.m_textParameters.ApplyParameters(originalTex) as Texture; } } } }
public override void UpdateModule(ProceduralObjectsLogic logic, bool simulationPaused, bool layerVisible) { if (!state) { point0 = new Vector3(parentObject.m_position.x, parentObject.m_position.y, parentObject.m_position.z); } else if (!simulationPaused && layerVisible) { float dt = Time.deltaTime * timeSpeed; MoveChildrenObj(dt); vy = vy - gravity * dt; parentObject.m_position = new Vector3( parentObject.m_position.x + dt * initialSpeed.x, parentObject.m_position.y + dt * vy, parentObject.m_position.z + dt * initialSpeed.z); if (parentObject.m_position.y < ProceduralUtils.NearestGroundPointVertical(parentObject.m_position).y) { parentObject.m_position.y = parentObject.m_position.y - dt * vy; vy = -vy * bounceFactor; if (t > 0) { t--; } else if (t == 0 || vy < 0.1f) { if (!repeat) { state = !state; } else { t = bounceTimes; parentObject.m_position = new Vector3(point0.x, point0.y, point0.z); vy = initialSpeed.y; MoveChildrenObj(-2f); MoveChildrenObj(-3f); } } } } }
public void TestBoop(SocketIOEvent e) { string[] arr = e.data["text"].ToString().Split(char.Parse(@"\")); string message = String.Join(null, arr); message = message.Substring(1, message.Length - 2); // Debug.Log(message); wsData = message; List <List <Vector3> > verticesList = new List <List <Vector3> >(); ProceduralUtils procedural = new ProceduralUtils(); verticesList = procedural.GetCoordinates(wsData); for (int i = 0; i < verticesList.Count; i++) { procedural.CreateMesh(verticesList[i], i); } verticesList.Clear(); if (e.data == null) { return; } }
public override void OnOpen(List <ProceduralObject> selection) { this.selection = POGroup.AllObjectsInSelection(selection, logic.selectedGroup); foreach (var po in this.selection) { if (po.meshStatus == 1) { continue; } try { po.historyEditionBuffer.InitializeNewStep(EditingStep.StepType.vertices, po.vertices); ProceduralUtils.RecenterObjOrigin(po, po.vertices); po.ApplyModelChange(); po.historyEditionBuffer.ConfirmNewStep(po.vertices); } catch (Exception e) { Debug.LogWarning("[ProceduralObjects] PO could not recenter object origin of object #" + po.id + " of type " + po.basePrefabName + "\n" + e); po.historyEditionBuffer.ConfirmNewStep(po.vertices); } } ExitAction(); }
public override CardDescription GenerateCard(int seed, CardGenerationFlags flags = CardGenerationFlags.NONE) { // First select the card type System.Random random = new System.Random(seed); // Still generate a type even if a flag is provided, so that the generation with a seed matches // ie. we don't want to generate 2 different creatures from the same seed just because we specified a creature flag CardType t = ProceduralUtils.GetRandomValue <CardType>(random, model); if ((flags & CardGenerationFlags.CREATURE) == CardGenerationFlags.CREATURE) { t = CardType.CREATURE; } else if ((flags & CardGenerationFlags.SPELL) == CardGenerationFlags.SPELL) { t = CardType.SPELL; } else if ((flags & CardGenerationFlags.TRAP) == CardGenerationFlags.TRAP) { t = CardType.TRAP; } switch (t) { case CardType.CREATURE: return(GenerateCreatureCard(random, model, images, creatureModelIndex, nameModel, flags)); case CardType.SPELL: return(GenerateSpellCard(random, model, images, creatureModelIndex, nameModel, flags)); case CardType.TRAP: return(GenerateTrapCard(random, model, images, creatureModelIndex, nameModel, flags)); } return(new CardDescription()); }
private float[,] GenerateTerrainData() { return(ProceduralUtils.GenerateTerrainData(size.x, size.y, scale / 1000f, baseAmplitude, octaves, lacunarity, persistence, offset)); }
protected override void UpdateTerrainData(float[,] data) { data = ProceduralUtils.IslandFilter(data, innerRadius, outerRadius); base.UpdateTerrainData(data); }
protected void UpdateTerrainTexture(float[,] data) { t.terrainData.alphamapResolution = size.x; t.terrainData.SetAlphamaps(0, 0, ProceduralUtils.GenerateTextureData(data, layers.ToArray())); }
static private bool GenerateCardEffect(System.Random random, IHistogram model, CreatureModelIndex creatureModels, CardEffectDescription effectDesc, EffectType effect, double minBudget, double maxBudget, bool positive) { IProceduralEffectGenerator effectGen = ProceduralUtils.GetProceduralGenerator(effect); effectGen.SetupParameters(random, model, creatureModels, minBudget, maxBudget); effectDesc.effectType = effectGen.Generate(); // Adjust budgets minBudget /= effectDesc.effectType.PowerLevel(); maxBudget /= effectDesc.effectType.PowerLevel(); if (minBudget > maxBudget) { double temp = minBudget; minBudget = maxBudget; maxBudget = temp; } // Always allow for default targetting (multiplier 1.0x) if (maxBudget < 1.0) { maxBudget = 1.0; } TargetType targetType = TargetType.CREATURES; SortedSet <TargetType> validTargets = CardEnums.GetValidFlags <TargetType>(effect); SortedSet <TargettingType> allowableTargetting = new SortedSet <TargettingType>(); SortedSet <QualifierType> allowableQualifiers = new SortedSet <QualifierType>(); while (validTargets.Count > 0 && allowableTargetting.Count == 0) { targetType = ProceduralUtils.GetRandomValue(random, model, validTargets); validTargets.Remove(targetType); switch (effectDesc.effectType.GetAlignment()) { case Alignment.POSITIVE: if (positive) { allowableTargetting = ProceduralUtils.GetTargettingByAlignment(Alignment.POSITIVE); allowableQualifiers = ProceduralUtils.GetQualifiersByAlignment(Alignment.NEUTRAL); allowableQualifiers.UnionWith(ProceduralUtils.GetQualifiersByAlignment(Alignment.POSITIVE)); allowableQualifiers.IntersectWith(CardEnums.GetValidFlags <QualifierType>(targetType)); if (allowableQualifiers.Count > 0) { allowableTargetting.UnionWith(ProceduralUtils.GetTargettingByAlignment(Alignment.NEUTRAL)); } } else { allowableTargetting = ProceduralUtils.GetTargettingByAlignment(Alignment.NEGATIVE); allowableQualifiers = ProceduralUtils.GetQualifiersByAlignment(Alignment.NEGATIVE); allowableQualifiers.IntersectWith(CardEnums.GetValidFlags <QualifierType>(targetType)); if (allowableQualifiers.Count > 0) { allowableTargetting.UnionWith(ProceduralUtils.GetTargettingByAlignment(Alignment.NEUTRAL)); } } break; case Alignment.NEGATIVE: if (positive) { allowableTargetting = ProceduralUtils.GetTargettingByAlignment(Alignment.NEGATIVE); allowableQualifiers = ProceduralUtils.GetQualifiersByAlignment(Alignment.NEUTRAL); allowableQualifiers.UnionWith(ProceduralUtils.GetQualifiersByAlignment(Alignment.NEGATIVE)); allowableQualifiers.IntersectWith(CardEnums.GetValidFlags <QualifierType>(targetType)); if (allowableQualifiers.Count > 0) { allowableTargetting.UnionWith(ProceduralUtils.GetTargettingByAlignment(Alignment.NEUTRAL)); } } else { allowableTargetting = ProceduralUtils.GetTargettingByAlignment(Alignment.POSITIVE); allowableQualifiers = ProceduralUtils.GetQualifiersByAlignment(Alignment.POSITIVE); allowableQualifiers.IntersectWith(CardEnums.GetValidFlags <QualifierType>(targetType)); if (allowableQualifiers.Count > 0) { allowableTargetting.UnionWith(ProceduralUtils.GetTargettingByAlignment(Alignment.NEUTRAL)); } } break; default: if (positive) { allowableTargetting = new SortedSet <TargettingType>((TargettingType[])Enum.GetValues(typeof(TargettingType))); allowableQualifiers = new SortedSet <QualifierType>((QualifierType[])Enum.GetValues(typeof(QualifierType))); allowableQualifiers.IntersectWith(CardEnums.GetValidFlags <QualifierType>(targetType)); } else { allowableTargetting = new SortedSet <TargettingType>(); } break; } allowableTargetting.IntersectWith(CardEnums.GetValidFlags <TargettingType>(targetType)); allowableTargetting.IntersectWith(CardEnums.GetValidFlags <TargettingType>(effectDesc.triggerCondition)); // Special case // Up to can never be a downside because you can choose 0 targets if (!positive) { allowableTargetting.Remove(TargettingType.UP_TO_TARGET); allowableTargetting.Remove(TargettingType.UP_TO_TARGET_ALLY); allowableTargetting.Remove(TargettingType.UP_TO_TARGET_ENEMY); } } // Could not find any valid targetting to achieve the desired alignment if (allowableTargetting.Count == 0) { SortedSet <TargetType> targets = CardEnums.GetValidFlags <TargetType>(effect); Debug.Log("Wasn't able to generate targets for effect <" + effect.ToString() + ">"); return(false); } // Attempt to narrow down the targetting pool SortedSet <TargettingType> targettingWithinBudget = new SortedSet <TargettingType>(allowableTargetting.Intersect(ProceduralUtils.GetTargettingWithinBudget(maxBudget))); if (targettingWithinBudget.Count > 0) { allowableTargetting = targettingWithinBudget; } else { Debug.Log("Unable to narrow down targetting types for <" + effect.ToString() + ", " + targetType.ToString() + "> for budget " + maxBudget); } TargettingType targettingType = ProceduralUtils.GetRandomValue(random, model, allowableTargetting); IProceduralTargettingGenerator targettingGen = ProceduralUtils.GetProceduralGenerator(targettingType); targettingGen.SetupParameters(targetType, random, model, minBudget, maxBudget); effectDesc.targettingType = targettingGen.Generate(); // Adjust budgets minBudget /= effectDesc.targettingType.PowerLevel(); maxBudget /= effectDesc.targettingType.PowerLevel(); if (minBudget > maxBudget) { double temp = minBudget; minBudget = maxBudget; maxBudget = temp; } if (effectDesc.targettingType is IQualifiableTargettingDescription qualifiable) { // Generate a possible qualifier // Attempt to narrow down the qualifier pool SortedSet <QualifierType> qualifiersWithinBudget = new SortedSet <QualifierType>(allowableQualifiers.Intersect(ProceduralUtils.GetQualifiersWithinBudget(maxBudget))); if (targettingWithinBudget.Count > 0) { allowableQualifiers = qualifiersWithinBudget; } else { Debug.Log("Unable to narrow down qualifier types for <" + effect.ToString() + ", " + targetType.ToString() + "> for budget " + maxBudget); } QualifierType qualifier = ProceduralUtils.GetRandomValue(random, model, allowableQualifiers); if (qualifier != QualifierType.NONE) { IProceduralQualifierGenerator qualifierGen = ProceduralUtils.GetProceduralGenerator(qualifier); qualifierGen.SetupParameters(random, model, minBudget, maxBudget); qualifiable.qualifier = qualifierGen.Generate(); } } return(true); }
static private CardDescription GenerateCreatureCard(System.Random random, IHistogram model, ImageGlossary images, CreatureModelIndex creatureModels, NameModel nameModel, CardGenerationFlags flags) { CreatureCardDescription card = ScriptableObject.CreateInstance(typeof(CreatureCardDescription)) as CreatureCardDescription; card.creatureType = ProceduralUtils.GetRandomValue <CreatureType>(random, model); if ((flags & CardGenerationFlags.HUMAN) == CardGenerationFlags.HUMAN) { card.creatureType = CreatureType.HUMAN; } else if ((flags & CardGenerationFlags.GOBLIN) == CardGenerationFlags.GOBLIN) { card.creatureType = CreatureType.GOBLIN; } else if ((flags & CardGenerationFlags.FAERIE) == CardGenerationFlags.FAERIE) { card.creatureType = CreatureType.FAERIE; } MultiCardHistogram combinedModel = ScriptableObject.CreateInstance(typeof(MultiCardHistogram)) as MultiCardHistogram; combinedModel.Init(new IHistogram[] { model, creatureModels.GetModel(card.creatureType) }); card.manaCost = (int)ProceduralUtils.GetRandomValue <ManaCost>(random, model); // Potentially generate a stronger body, but with a drawback double bodyManaCost = GetCreatureBodyBudget(creatureModels.GetBodyLambda(card.creatureType), random.Next(), card.manaCost + 1); int maxStats = PowerBudget.StatBudget(bodyManaCost); // Decide on stats card.health = GetHealth(random, creatureModels.GetStatProbability(card.creatureType, (int)Math.Round(bodyManaCost, MidpointRounding.AwayFromZero)), maxStats); card.attack = maxStats - card.health; // Decide on power budget double powerBudget = PowerBudget.ManaPowerBudgets[card.manaCost]; double powerMargin = PowerBudget.ManaPowerMargin[card.manaCost]; double powerLimit = PowerBudget.ManaPowerLimit[card.manaCost]; card.cardName = "A creature card"; //card.name += "(" + powerBudget.ToString() + ")"; // Decide on keyword attributes int maxKeywords = 3; for (int i = 0; i < maxKeywords; i++) { double keywordPowerLimit = powerLimit - card.PowerLevel(); if (keywordPowerLimit < 0) { keywordPowerLimit = 0; } KeywordAttribute keyword = ProceduralUtils.GetRandomValue(random, combinedModel, ProceduralUtils.GetKeywordsWithinBudget(keywordPowerLimit, card.attack, card.health)); if (keyword == KeywordAttribute.NONE) { break; } card.AddAttribute(keyword); } // Decide on effects GenerateCardEffects(random, combinedModel, creatureModels, card, powerBudget, powerMargin, powerLimit); // Revise the mana cost based on what effects we actually did generate int revisedMana = PowerBudget.PowerLevelToMana(card.PowerLevel()); if (revisedMana != card.manaCost) { Debug.Log("Had to revise the mana cost from " + card.manaCost.ToString() + " to " + revisedMana.ToString()); card.manaCost = revisedMana; } card.image = ProceduralUtils.GetRandomTexture(random, images.GetCreatureImages(card.creatureType)); CardTags tags = CardTagging.GetCardTags(card); card.cardName = nameModel.GenerateName(random, tags); return(card); }
static private void GenerateCardEffects(System.Random random, IHistogram model, CreatureModelIndex creatureModels, CardDescription cardDesc, double powerBudget, double powerMargin, double powerLimit) { // A trap card only has one trigger condition if (cardDesc.cardType == CardType.TRAP) { ProceduralUtils.GetRandomValue(random, model, CardEnums.GetValidFlags <TriggerCondition>(CardType.TRAP)); } int effectCount = 0; List <TriggerCondition> triggerBlacklist = new List <TriggerCondition>(); while ((cardDesc.PowerLevel() + PowerBudget.FLAT_EFFECT_COST) < powerBudget && effectCount < EffectConstants.MAX_CARD_EFFECTS) { // Generate effects CardEffectDescription cardEffect = new CardEffectDescription(); // Create effects with a power level ranging between using max limit of budget, or uniformly distributing the min budget double maxAllowableBudget = powerLimit - cardDesc.PowerLevel() - PowerBudget.FLAT_EFFECT_COST; double minAllowableBudget = (powerBudget - cardDesc.PowerLevel() - PowerBudget.FLAT_EFFECT_COST) / (EffectConstants.MAX_CARD_EFFECTS - effectCount); if (cardDesc.cardType == CardType.SPELL || (cardDesc.cardType == CardType.TRAP && effectCount > 0)) { // After the first condition of a trap or after casting a spell all further effects of // the card should just resolve so trigger cond is NONE cardEffect.triggerCondition = TriggerCondition.NONE; // If NONE has been blacklisted that means that there are no candidates for the remaining budget if (triggerBlacklist.Contains(TriggerCondition.NONE)) { //Debug.Log("No effects are valid for budget " + maxAllowableBudget); break; } } else { if (ProceduralUtils.FlagsExist(triggerBlacklist, CardEnums.GetValidFlags <TriggerCondition>(cardDesc.cardType))) { cardEffect.triggerCondition = ProceduralUtils.GetRandomValueExcluding(random, model, triggerBlacklist, CardEnums.GetValidFlags <TriggerCondition>(cardDesc.cardType)); } else { // No triggers available mean each trigger type has been blacklisted //Debug.Log("No effects are valid for budget " + maxAllowableBudget); break; } } double triggerBudgetModifier = PowerBudget.GetTriggerModifier(cardEffect.triggerCondition, cardDesc); maxAllowableBudget /= triggerBudgetModifier; minAllowableBudget /= triggerBudgetModifier; SortedSet <EffectType> candidatesWithinBudget = ProceduralUtils.GetEffectsWithinBudget(maxAllowableBudget); if (candidatesWithinBudget.Count == 0) { triggerBlacklist.Add(cardEffect.triggerCondition); Debug.Log("No effects are valid for budget " + maxAllowableBudget); continue; } bool validEffect = false; SortedSet <EffectType> effectCandidates = new SortedSet <EffectType>(CardEnums.GetValidFlags <EffectType>(cardEffect.triggerCondition).Intersect(candidatesWithinBudget)); effectCandidates.Remove(EffectType.NONE); while (!validEffect && effectCandidates.Count > 0) { EffectType effectType = ProceduralUtils.GetRandomValueExcluding(random, model, new EffectType[] { EffectType.NONE }, effectCandidates); // This means that there isn't an effect that meets this condition if (effectType == EffectType.NONE) { // Add to black list so we don't get multiple effects that trigger on same condition if (cardEffect.triggerCondition != TriggerCondition.NONE) { triggerBlacklist.Add(cardEffect.triggerCondition); } break; } validEffect = GenerateCardEffect(random, model, creatureModels, cardEffect, effectType, minAllowableBudget, maxAllowableBudget, true); } // This means that there isn't an effect that meets this condition if (validEffect) { cardDesc.cardEffects.Add(cardEffect); effectCount++; } else { Debug.Log("No valid effect could be generated for trigger <" + cardEffect.triggerCondition.ToString() + "> with budget " + maxAllowableBudget); } // Add to black list so we don't get multiple effects that trigger on same condition if (cardEffect.triggerCondition != TriggerCondition.NONE) { triggerBlacklist.Add(cardEffect.triggerCondition); } } // Generate a draw back while (cardDesc.PowerLevel() > powerMargin) { // TODO: Drawback should be one of, additional cost, negative effect, or negative modification to existing effect // For now just add additional negative effect CardEffectDescription cardEffect = new CardEffectDescription(); double maxAllowableBudget = (cardDesc.PowerLevel() - powerBudget - PowerBudget.FLAT_EFFECT_COST) / PowerBudget.DOWNSIDE_WEIGHT; double minAllowableBudget = (cardDesc.PowerLevel() - powerMargin - PowerBudget.FLAT_EFFECT_COST) / PowerBudget.DOWNSIDE_WEIGHT; if (cardDesc.cardType == CardType.SPELL || (cardDesc.cardType == CardType.TRAP && effectCount > 0)) { // After the first condition of a trap or after casting a spell all further effects of // the card should just resolve so trigger cond is NONE cardEffect.triggerCondition = TriggerCondition.NONE; // If NONE has been blacklisted that means that there are no candidates for the remaining budget if (triggerBlacklist.Contains(TriggerCondition.NONE)) { Debug.Log("No effects are valid for budget " + maxAllowableBudget); break; } } else { if (ProceduralUtils.FlagsExist(triggerBlacklist, CardEnums.GetValidFlags <TriggerCondition>(cardDesc.cardType))) { cardEffect.triggerCondition = ProceduralUtils.GetRandomValueExcluding(random, model, triggerBlacklist, CardEnums.GetValidFlags <TriggerCondition>(cardDesc.cardType)); } else { // No triggers available mean each trigger type has been blacklisted Debug.Log("No effects are valid for budget " + maxAllowableBudget); break; } } double triggerBudgetModifier = PowerBudget.GetTriggerModifier(cardEffect.triggerCondition, cardDesc); maxAllowableBudget /= triggerBudgetModifier; minAllowableBudget /= triggerBudgetModifier; SortedSet <EffectType> candidatesWithinBudget = ProceduralUtils.GetEffectsWithinBudget(maxAllowableBudget); if (candidatesWithinBudget.Count == 0) { triggerBlacklist.Add(cardEffect.triggerCondition); Debug.Log("No effects are valid for budget " + maxAllowableBudget); continue; } bool validEffect = false; SortedSet <EffectType> effectCandidates = new SortedSet <EffectType>(CardEnums.GetValidFlags <EffectType>(cardEffect.triggerCondition).Intersect(candidatesWithinBudget)); effectCandidates.Remove(EffectType.NONE); while (!validEffect && effectCandidates.Count > 0) { EffectType effectType = ProceduralUtils.GetRandomValueExcluding(random, model, new EffectType[] { EffectType.NONE }, effectCandidates); // This means that there isn't an effect that meets this condition if (effectType == EffectType.NONE) { // Add to black list so we don't get multiple effects that trigger on same condition if (cardEffect.triggerCondition != TriggerCondition.NONE) { triggerBlacklist.Add(cardEffect.triggerCondition); } break; } validEffect = GenerateCardEffect(random, model, creatureModels, cardEffect, effectType, minAllowableBudget, maxAllowableBudget, false); } // This means that there isn't an effect that meets this condition if (validEffect) { cardDesc.cardEffects.Add(cardEffect); break; } else { Debug.Log("No valid effect could be generated for trigger <" + cardEffect.triggerCondition.ToString() + "> with budget " + -maxAllowableBudget); } // Add to black list so we don't get multiple effects that trigger on same condition if (cardEffect.triggerCondition != TriggerCondition.NONE) { triggerBlacklist.Add(cardEffect.triggerCondition); } } }