Ejemplo n.º 1
0
    Tile GenerateTileAt(int x, int y)
    {
        // Get the terrain type.
        TerrainType t = GenerateTerrainTypeAt(x, y);

        // Create the tile.
        Tile tile = new Tile(x, y, t);

        // Set the tile.
        tileMap.SetAt(x, y, tile);

        // Should a creature spawn here?
        if (GC.Chance(P_CREATURE_ON_TILE))
        {
            // Yes. Get which one from the tile type.
            CreatureType ct = t.GetRandomCreatureType();

            tile.entity = new Creature(ct, tile);
        }

        // Should an item spawn here?
        if (GC.Chance(P_ITEM_ON_TILE))
        {
            // Yes. Get which one from the tile type.
            ItemType it = t.GetRandomItemType();

            tile.storedItem = it;
        }

        // Return the tile.
        return(tile);
    }
Ejemplo n.º 2
0
    public void GenerateStancesWithOtherCreatures()
    {
        if (creatureStances != null)
        {
            Debug.LogError("Creature Stances Already Generated!");
            return;
        }

        creatureStances = new Dictionary <CreatureType, Stance> ();

        // Loop through each other creature.
        foreach (CreatureType creatureType in creatureTypes)
        {
            Stance stance;

            // Calculate the relative difficulty of this creature to ours. Rough max of about 2.5 means it is way stronger than ours. Rough min of about 2.5 means it is way weaker.
            // Note these "maximums" will be exceeded by maybe 1 or 2 creatures each game, and were calculated by trial and error, nothing rigorous.
            float relDiff = creatureType.diff - diff;

            // If relDiff is largeish then we will be at least semi-hostile to it.
            // If relDiff is smallish then we will be at least semi-neutral to it.
            // If relDiff is large in magnitude then we will be less likely to be semi.

            if (Random.Range(-RANDOMNESS_FOR_HOSTILE_OR_EVASIVE, RANDOMNESS_FOR_HOSTILE_OR_EVASIVE) + relDiff > 0)
            {
                // HOSTILE

                if (GC.Chance(BASE_PROB_SEMI * GC.ReMap(Mathf.Abs(relDiff), 0f, 2.5f, 1.2f, 0.8f)))
                {
                    // SEMI HOSTILE
                    stance = Stance.SemiHostile;
                }
                else
                {
                    // HOSTILE
                    stance = Stance.Hostile;
                }
            }
            else
            {
                // EVASIVE
                if (GC.Chance(BASE_PROB_SEMI * GC.ReMap(Mathf.Abs(relDiff), 0f, 2.5f, 1.2f, 0.8f)))
                {
                    // SEMI EVASIVE
                    stance = Stance.SemiEvasive;
                }
                else
                {
                    // EVASIVE
                    stance = Stance.Evasive;
                }
            }

            creatureStances.Add(creatureType, stance);
        }
    }
Ejemplo n.º 3
0
    public static ItemType GenerateNewCraftedItemType(Sprite sprite, Color color)
    {
        // Create the empty item type object.
        ItemType it = new ItemType();

        it.sprite = sprite;
        it.color  = color;

        // Determine the health effect.
        it.healthEffect = (int)(CRAFTED_MAX_HEALTH_EFFECT * (Mathf.Pow(Random.Range(0f, 1f), 3) - 0.2f));
        it.rarity      *= Mathf.Pow(CRAFTED_HEALTH_EFFECT_RARITY_MOD, it.healthEffect);

        // Determine the melee damage.
        it.meleeDamage = (int)(CRAFTED_MAX_MELEE_DAMAGE * Random.Range(0f, 1f) * GC.ReMap(it.rarity, 0.8f, 10f, 1f, -0.3f));
        if (it.meleeDamage < 1)
        {
            it.meleeDamage = 1;
        }
        it.rarity *= Mathf.Pow(CRAFTED_MELEE_DAMAGE_RARITY_MOD, it.meleeDamage);

        // Determine the melee range.
        it.meleeRange = (int)(CRAFTED_MAX_MELEE_RANGE * Random.Range(0f, 1f) * GC.ReMap(it.rarity, 0.8f, 10f, 1f, 0.1f));
        if (it.meleeRange < 1)
        {
            it.meleeRange = 1;
        }
        it.rarity *= Mathf.Pow(CRAFTED_MELEE_RANGE_RARITY_MOD, it.meleeDamage - 2);

        // Determine the throw damage.
        it.throwDamage = (int)(CRAFTED_MAX_THROW_DAMAGE * Random.Range(0f, 1f) * GC.ReMap(it.rarity, 0.75f, 20f, 1f, 0.1f));
        if (it.throwDamage < 1)
        {
            it.throwDamage = 1;
        }
        it.rarity *= Mathf.Pow(CRAFTED_THROW_DAMAGE_RARITY_MOD, it.throwDamage - 2);

        // Determine the throw range.
        it.throwRange = (int)(GC.ReMap(Random.Range(0f, 1f) * GC.ReMap(it.rarity, 0.75f, 30f, 1f, 0.5f), 0f, 1f, it.meleeRange + CRAFTED_MIN_ADDITIONAL_RANGED_RANGE, CRAFTED_MAX_THROW_RANGE));
        it.throwRange = Mathf.Clamp(it.throwRange, it.meleeRange + CRAFTED_MIN_ADDITIONAL_RANGED_RANGE, CRAFTED_MAX_THROW_RANGE);
        it.rarity    *= Mathf.Pow(CRAFTED_THROW_RANGE_RARITY_MOD, it.throwRange - (CRAFTED_MAX_THROW_RANGE - it.meleeRange - CRAFTED_MIN_ADDITIONAL_RANGED_RANGE) / 2);


        // Determine whether "throwing" uses an alternate ammo and hence is more like firing.
        if (GC.Chance(BASE_PROB_ALTERNATE_AMMO_FOR_THROWS * GC.ReMap(it.throwRange, it.meleeRange + CRAFTED_MIN_ADDITIONAL_RANGED_RANGE, CRAFTED_MAX_THROW_RANGE, 0.5f, 1.5f)))
        {
            //TODO How to decide what to use as ammo? Should be cheap, and even cheaper if this item has a high rarity.
        }

        it.rarity /= 3;
        //Debug.Log ( "Health Effect: " + it.healthEffect + ", Melee Damage: " + it.meleeDamage + ", Melee Range: " + it.meleeRange + ", Throw Damage: " + it.throwDamage + ", Throw Range: " + it.throwRange + ", Rarity: " + it.rarity);

        return(it);
    }
Ejemplo n.º 4
0
    /// <summary>
    /// Creates a new <see cref="TerrainType"/> and adds it to the public list of terrain types.
    /// </summary>
    /// <param name="spriteName">The name of the sprite for this terrain type.</param>
    TerrainType(Sprite sprite, Color color)
    {
        // Set the sprite for this terrain type.
        this.sprite = sprite;

        // Set the colour for this terrain type.
        this.color = color;

        // Determine the speed for this terrain type.
        if (GC.Chance(P_ABNORMAL_TERRAIN_SPEED))
        {
            // We want a non-default terrain speed, so have equal chance of double or half speed terrain.
            if (GC.Chance(0.5f))
            {
                terrainSpeed = 1;
            }
            else
            {
                terrainSpeed = 4;
            }

            // Increase this terrains rarity for having non-default terrain speed.
            rarity *= ABNORMAL_TERRAIN_SPEED_RARITY_MOD;
        }
        else
        {
            // We want default terrain speed.
            terrainSpeed = 2;
        }

        // Determine whether this terrain will deal damage to the player or not.
        if (GC.Chance(P_DAMAGE_PER_TURN))
        {
            // Calculate how much damage per turn.
            damagePerTurn = Random.Range(1, MAX_DAMAGE_PER_TURN + 1);

            // Adjust rarity accordingly.
            rarity *= Mathf.Pow(RARITY_PER_DAMAGE_PER_TURN, damagePerTurn);
        }
        else
        {
            // No damage per turn.
            damagePerTurn = 0;
        }

        // Add this to the list of terrain types.
        terrainTypes.Add(this);
    }
Ejemplo n.º 5
0
    public override void SelectNewAction()
    {
        // Firstly, do we have a target?
        if (target != null)
        {
            // Can we still see the target?
            if (target.dead || SquareDistance(target) >= creatureType.sightRange * creatureType.sightRange)
            {
                // Not any more.
                target = null;
            }
        }

        // We still may or may not have a target. If we don't, try to find one.
        if (target == null)
        {
            // For now just do a box search starting with a box of radius 1, with the radius increasing.
            for (int r = 0; r < creatureType.sightRange; r++)
            {
                // Left and right column.
                for (int y = -r; y <= r; y++)
                {
                    if (TrySetTarget(-r, y) || TrySetTarget(r, y))
                    {
                        break;
                    }
                }

                if (target != null)
                {
                    break;
                }

                // Top and bottom row.
                for (int x = t.x - r + 1; x <= t.x + r - 1; x++)
                {
                    if (TrySetTarget(x, -r) || TrySetTarget(x, r))
                    {
                        break;
                    }
                }

                if (target != null)
                {
                    break;
                }
            }
        }

        // Finally act based on whether or not there is a target.
        if (target != null)
        {
            // We have a target.
            CreatureType.Stance stance;
            if (target is Player)
            {
                stance = creatureType.playerStance;
            }
            else if (target is Creature)
            {
                creatureType.creatureStances.TryGetValue(((Creature)target).creatureType, out stance);
            }
            else
            {
                // This shouldn't happen, and is not coded for yet.
                Debug.LogError("MoveableEntity is neither creature nor player.");
                stance = CreatureType.Stance.Hostile;
            }

            // If we can attack it we should, but only if hostile or semi hostile.
            if ((stance == CreatureType.Stance.Hostile || stance == CreatureType.Stance.SemiHostile) && attackCooldown <= 0 && SquareDistance(target) < GetAttackRange() * GetAttackRange())
            {
                TryAttack(target);
            }
            else
            {
                // We can't attack it so move closer. First find out our relative position.
                int relx = t.x - target.t.x;
                int rely = t.y - target.t.y;

                // Also calculate their norm.
                int nx = Mathf.Abs(relx);
                int ny = Mathf.Abs(rely);

                // Normalise the relative ones so that they are only 1 or -1.
                if (nx != 0)
                {
                    relx /= nx;
                }
                if (ny != 0)
                {
                    rely /= ny;
                }

                // Now randomly choose to either move in the x direction or the y direction.
                int r = Random.Range(0, nx + ny);

                bool anyEvasive = stance == CreatureType.Stance.Evasive || stance == CreatureType.Stance.SemiEvasive;

                if (r < relx)
                {
                    if (anyEvasive)
                    {
                        // Try to move in the y direction first.
                        TryMoveTo(t.x, t.y + rely);
                    }
                    else
                    {
                        // Try to move in the x direction first.
                        TryMoveTo(t.x - relx, t.y);
                    }
                }
                else
                {
                    if (anyEvasive)
                    {
                        // Try to move in the x direction first.
                        TryMoveTo(t.x + relx, t.y);
                    }
                    else
                    {
                        // Try to move in the y direction first.
                        TryMoveTo(t.x, t.y - rely);
                    }
                }

                // If we didn't move, then try reversing things.
                if (actionTimer <= 0)
                {
                    if (r >= relx)
                    {
                        if (anyEvasive)
                        {
                            // Try to move in the y direction now.
                            TryMoveTo(t.x, t.y + rely);
                        }
                        else
                        {
                            // Try to move in the x direction now.
                            TryMoveTo(t.x - relx, t.y);
                        }
                    }
                    else
                    {
                        if (anyEvasive)
                        {
                            // Try to move in the x direction now.
                            TryMoveTo(t.x + relx, t.y);
                        }
                        else
                        {
                            // Try to move in the y direction now.
                            TryMoveTo(t.x, t.y - rely);
                        }
                    }
                }

                // If that didn't work either then we will just stay here for now and pass.
            }
        }
        else
        {
            // There is no target. Walk in a random direction or else stay still.
            if (GC.Chance(P_NO_TARGET_IDLE))
            {
                // Don't do anything.
                return;
            }
            else
            {
                // Move randomly.
                int r = Random.Range(0, 2);
                if (r == 0)
                {
                    r = -1;
                }
                if (Random.Range(0, 2) == 0)
                {
                    TryMoveTo(t.x + r, t.y);
                }
                else
                {
                    TryMoveTo(t.x, t.y + r);
                }
            }
        }
    }
Ejemplo n.º 6
0
    /// <summary>
    /// Generates a new <see cref="CreatureType"/> and adds it to the public list of creature types.
    /// </summary>
    /// <param name="spriteName">The name of the sprite for this terrain type.</param>
    CreatureType(Sprite sprite, Color color)
    {
        // Set the sprite and colour for this creature type.
        this.sprite = sprite;
        this.color  = color;

        // Decide on the move speed of the creature.
        if (GC.Chance(P_ABNORMAL_SPEED))
        {
            if (GC.Chance(P_FAST_GIVEN_ABONORMAL_SPEED))
            {
                moveSpeed = 4;
                diff     *= DIFF_MOD_IF_FAST;
            }
            else
            {
                moveSpeed = 1;
                diff     *= DIFF_MOD_IF_SLOW;
            }
        }
        else
        {
            moveSpeed = 2;
        }

        // Decide on the attack range of the creature. Decrease the maximum if difficulty is high, then readjust difficulty.
        attackRange = Random.Range(MIN_ATTACK_RANGE, Mathf.Min(1 + MAX_ATTACK_RANGE, 1 + (int)(MAX_ATTACK_RANGE / diff)));
        diff       *= GC.ReMap(attackRange, MIN_ATTACK_RANGE, MAX_ATTACK_RANGE, 0.5f, 1.5f);

        // Decide on the sight range of the creature. Should be at least a little bit more than the attack range.
        sightRange = Random.Range(attackRange + MIN_GAP_BETWEEN_SIGHT_AND_ATTACK, Mathf.Min(1 + MAX_SIGHT_RANGE, 1 + (int)(MAX_SIGHT_RANGE / diff)));
        diff      *= GC.ReMap(sightRange, attackRange + MIN_GAP_BETWEEN_SIGHT_AND_ATTACK, MAX_SIGHT_RANGE, 0.9f, 1.1f);

        // Calculate attack damage.
        attackDamage = Random.Range(Mathf.Max(MIN_ATTACK_DAMAGE, (int)(MIN_ATTACK_DAMAGE / diff)), Mathf.Min(1 + MAX_ATTACK_DAMAGE, 1 + (int)(MAX_ATTACK_DAMAGE / diff)));
        diff        *= GC.ReMap(attackDamage, MIN_ATTACK_DAMAGE, MAX_ATTACK_DAMAGE, 0.5f, 2f);

        // Calculate the attack cooldown.
        attackCooldown  = Random.Range(0, 1 + INIT_ATTACK_COOLDOWN_MAX);
        attackCooldown += (int)GC.ReMap(diff, 0.5f, 2f, MIN_ATTACK_COOLDOWN_ADDITION, MAX_ATTACK_COOLDOWN_ADDITION);
        attackCooldown  = Mathf.Clamp(attackCooldown, MIN_ATTACK_COOLDOWN_ADDITION, MAX_ATTACK_COOLDOWN_ADDITION + INIT_ATTACK_COOLDOWN_MAX);
        diff           *= GC.ReMap(attackCooldown, MIN_ATTACK_COOLDOWN_ADDITION, MAX_ATTACK_COOLDOWN_ADDITION + INIT_ATTACK_COOLDOWN_MAX, 2f, 0.5f);

        // Calculate health.
        float fhealth = Random.Range(0f, 1f);

        fhealth  = fhealth * fhealth;
        fhealth /= diff;
        health   = (int)GC.ReMap(fhealth, 0f, 2f, MIN_HEALTH, 1 + MAX_HEALTH);
        health   = Mathf.Clamp(health, MIN_HEALTH, MAX_HEALTH);
        diff    *= GC.ReMap(health, MIN_HEALTH, MAX_HEALTH, 0.5f, 3f);

        /*
         *      Debug.Log ("Seed: " + moveSpeed.ToString() + ", Range: " + attackRange.ToString() + ", Sight: " + sightRange.ToString()
         + ", Damage: " + attackDamage.ToString() + ", Cooldown: " + attackCooldown.ToString() + ", Health: " + health.ToString()
         + ", Diff: " +  diff.ToString());
         */

        // Decide how this creature interacts with the player. More likely to be hostile if strong.
        if (GC.Chance(BASE_PROB_HOSTILE_OR_SEMI_PLAYER * GC.ReMap(diff, 0.5f, 2f, 0.75f, 1.5f)))
        {
            // HOSTILE

            // Decide if semi hostile. More likely to be semi hostile if strong or weak.
            if (GC.Chance(BASE_PROB_SEMI_IF_HOSTILE_PLAYER * GC.ReMap(Mathf.Abs(diff - 1.25f), 0f, 0.75f, 1.5f, 0.5f)))
            {
                // SEMI HOSTILE.
                playerStance = Stance.SemiHostile;
            }
            else
            {
                // HOSTILE.
                playerStance = Stance.Hostile;
            }
        }
        else
        {
            // EVASIVE

            // Decide if semi evasive or evasive. More likely to be semi evasive if strong.
            if (GC.Chance(BASE_PROB_SEMI_IF_EVASIVE_PLAYER * GC.ReMap(diff, 0.5f, 2f, 1.1f, 0.9f)))
            {
                // SEMI EVASIVE
                playerStance = Stance.SemiEvasive;
            }
            else
            {
                // SEMI HOSTILE
                playerStance = Stance.SemiHostile;
            }
        }

        // How this creature interacts with each other creature will be calculated after all creatures have been calculated.

        // We shall now calculate this creatures base spawn weight.
        float baseSpawnProb = GC.ReMap(diff, 0.5f, 2f, 1f, 0f);

        baseSpawnProb = Mathf.Clamp(baseSpawnProb, 0f, 1f);

        // We shall now calculate its spawn weight for each biome.
        foreach (TerrainType terrainType in TerrainType.terrainTypes)
        {
            terrainType.spawnWeightPerCreature.Add(this, baseSpawnProb * Mathf.Pow(Random.Range(0f, 1f), 3));
        }

        // Add this creature to the list of creature types.
        creatureTypes.Add(this);
    }