Пример #1
0
 protected void CheckFootfalls()
 {
     if (!isGrounded && !isInWater)
     {
         Vector3 curPos = transform.position;
         int     x      = (int)curPos.x;
         int     y      = (int)curPos.y;
         int     z      = (int)curPos.z;
         if (x != lastPosX || y != lastPosY || z != lastPosZ)
         {
             lastPosX = x;
             lastPosY = y;
             lastPosZ = z;
             VoxelIndex index = env.GetVoxelUnderIndex(curPos, true);
             if (index.typeIndex != lastVoxelTypeIndex)
             {
                 lastVoxelTypeIndex = index.typeIndex;
                 if (lastVoxelTypeIndex != 0)
                 {
                     VoxelDefinition vd = index.type;
                     SetFootstepSounds(vd.footfalls, vd.landingSound, vd.jumpSound);
                     if (vd.triggerWalkEvent && OnVoxelWalk != null)
                     {
                         OnVoxelWalk(index.chunk, index.voxelIndex);
                     }
                     CheckDamage(vd);
                 }
             }
         }
     }
 }
        void GetCrumblyVoxelRecursive(Vector3 originalPosition, Vector3 position, int amount, List <VoxelIndex> voxelIndices)
        {
            if (tempVoxelIndicesCount >= amount)
            {
                return;
            }

            VoxelChunk chunk;
            int        voxelIndex;
            int        c = 0;
            bool       dummy;

            for (int k = 0; k < collapsingOffsets.Length; k += 3)
            {
                Vector3 pos = position;
                pos.x += collapsingOffsets [k];
                pos.y += collapsingOffsets [k + 1];
                pos.z += collapsingOffsets [k + 2];
                float dx = pos.x > originalPosition.x ? pos.x - originalPosition.x : originalPosition.x - pos.x;
                float dz = pos.z > originalPosition.z ? pos.z - originalPosition.z : originalPosition.z - pos.z;
                if (dx > 8 || dz > 8)
                {
                    continue;
                }
                if (!tempVoxelPositions.TryGetValue(pos, out dummy))
                {
                    tempVoxelPositions [pos] = true;
                    if (GetVoxelIndex(pos, out chunk, out voxelIndex, false) && chunk.voxels [voxelIndex].hasContent == 1 && chunk.voxels [voxelIndex].opaque >= 3 && voxelDefinitions [chunk.voxels [voxelIndex].typeIndex].willCollapse)
                    {
                        VoxelIndex vi = new VoxelIndex();
                        vi.chunk      = chunk;
                        vi.voxelIndex = voxelIndex;
                        vi.position   = pos;
                        voxelIndices.Add(vi);
                        tempVoxelIndicesCount++;
                        c++;
                        if (tempVoxelIndicesCount >= amount)
                        {
                            break;
                        }
                    }
                }
            }
            int lastCount = tempVoxelIndicesCount;

            for (int k = 1; k <= c; k++)
            {
                GetCrumblyVoxelRecursive(originalPosition, tempVoxelIndices [lastCount - k].position, amount, voxelIndices);
            }
        }
        int DamageAreaFast(Vector3 origin, int damage, int damageRadius = 1, bool distanceAttenuation = true, bool addParticles = true, List <VoxelIndex> results = null)
        {
            bool hasResults = results != null;

            if (hasResults)
            {
                results.Clear();
            }
            if (damageRadius < 0 || damage < 1)
            {
                return(0);
            }

            int          damagedCount = 0;
            Vector3      direction    = Misc.vector3zero;
            VoxelHitInfo hitInfo;

            GetVoxelIndices(origin, damageRadius, tempVoxelIndices);
            int count = tempVoxelIndices.Count;

            for (int k = 0; k < count; k++)
            {
                VoxelIndex vi         = tempVoxelIndices [k];
                VoxelChunk otherChunk = vi.chunk;
                int        otherIndex = vi.voxelIndex;
                int        dam        = damage;
                if (distanceAttenuation && vi.sqrDistance > 1)
                {
                    dam = (int)(damage * damageRadius * damageRadius / vi.sqrDistance);
                }
                if (dam > 0 && GetVoxelVisibility(otherChunk, otherIndex))
                {
                    FastVector.NormalizedDirection(ref origin, ref vi.position, ref direction);
                    if (RayCastFast(origin, direction, out hitInfo, damageRadius, false, 5))
                    {
                        int damageTaken = DamageVoxelFast(ref hitInfo, dam, addParticles, false);
                        if (hasResults)
                        {
                            VoxelIndex di = vi;
                            di.damageTaken = damageTaken;
                            results.Add(di);
                            damagedCount++;
                        }
                    }
                }
            }

            return(damagedCount);
        }
Пример #4
0
        void CreateTree(Vector3 position, ModelDefinition tree, int rotation)
        {
            if ((object)tree == null)
            {
                return;
            }
            if (OnTreeBeforeCreate != null)
            {
                if (!OnTreeBeforeCreate(position))
                {
                    return;
                }
            }

            Vector3 pos;

            treeChunkRefreshRequests.Clear();
            VoxelChunk lastChunk    = null;
            int        modelOneYRow = tree.sizeZ * tree.sizeX;
            int        modelOneZRow = tree.sizeX;
            int        halfSizeX    = tree.sizeX / 2;
            int        halfSizeZ    = tree.sizeZ / 2;
            int        tmp;
            VoxelIndex index         = new VoxelIndex();
            bool       informIndices = false;

            if (OnTreeAfterCreate != null)
            {
                informIndices = true;
                tempVoxelIndices.Clear();
            }

            for (int b = 0; b < tree.bits.Length; b++)
            {
                int bitIndex = tree.bits [b].voxelIndex;
                int py       = bitIndex / modelOneYRow;
                int remy     = bitIndex - py * modelOneYRow;
                int pz       = remy / modelOneZRow;
                int px       = remy - pz * modelOneZRow;

                // Random rotation
                switch (rotation)
                {
                case 0:
                    tmp = px;
                    px  = halfSizeZ - pz;
                    pz  = tmp - halfSizeX;
                    break;

                case 1:
                    tmp = px;
                    px  = pz - halfSizeZ;
                    pz  = tmp - halfSizeX;
                    break;

                case 2:
                    tmp = px;
                    px  = pz - halfSizeZ;
                    pz  = halfSizeX - tmp;
                    break;

                default:
                    px -= halfSizeX;
                    pz -= halfSizeZ;
                    break;
                }

                pos.x = position.x + tree.offsetX + px;
                pos.y = position.y + tree.offsetY + py;
                pos.z = position.z + tree.offsetZ + pz;

                VoxelChunk chunk;
                int        voxelIndex;

                if (GetVoxelIndex(pos, out chunk, out voxelIndex))
                {
                    if (!chunk.modified && (chunk.voxels [voxelIndex].opaque < FULL_OPAQUE || voxelDefinitions [chunk.voxels [voxelIndex].typeIndex].renderType == RenderType.CutoutCross))
                    {
                        VoxelDefinition treeVoxel = tree.bits [b].voxelDefinition ?? defaultVoxel;
                        chunk.voxels [voxelIndex].Set(treeVoxel, tree.bits [b].finalColor);
                        if (informIndices)
                        {
                            index.chunk      = chunk;
                            index.voxelIndex = voxelIndex;
                            index.position   = pos;
                            tempVoxelIndices.Add(index);
                        }
                        if (py == 0)
                        {
                            // fills one voxel beneath with tree voxel to avoid the issue of having some trees floating on some edges/corners
                            if (voxelIndex >= ONE_Y_ROW)
                            {
                                if (chunk.voxels [voxelIndex - ONE_Y_ROW].hasContent != 1)
                                {
                                    chunk.voxels [voxelIndex - ONE_Y_ROW].Set(treeVoxel, tree.bits [b].finalColor);
                                    if (informIndices)
                                    {
                                        index.chunk      = chunk;
                                        index.voxelIndex = voxelIndex - ONE_Y_ROW;
                                        index.position   = pos;
                                        index.position.y--;
                                        tempVoxelIndices.Add(index);
                                    }
                                }
                            }
                            else
                            {
                                VoxelChunk bottom = chunk.bottom;
                                if (bottom != null && !bottom.modified)
                                {
                                    int bottomIndex = voxelIndex + (CHUNK_SIZE - 1) * ONE_Y_ROW;
                                    if (bottom.voxels [bottomIndex].hasContent != 1)
                                    {
                                        chunk.voxels [bottomIndex].Set(treeVoxel, tree.bits [b].finalColor);
                                        if (informIndices)
                                        {
                                            index.chunk      = bottom;
                                            index.voxelIndex = bottomIndex;
                                            index.position   = pos;
                                            index.position.y--;
                                            tempVoxelIndices.Add(index);
                                        }
                                        if (!treeChunkRefreshRequests.Contains(bottom))
                                        {
                                            treeChunkRefreshRequests.Add(bottom);
                                        }
                                    }
                                }
                            }
                        }
                        if (chunk != lastChunk)
                        {
                            lastChunk = chunk;
                            if (!chunk.inqueue && !treeChunkRefreshRequests.Contains(chunk))
                            {
                                treeChunkRefreshRequests.Add(chunk);
                            }
                        }
                    }
                }
            }
            treesCreated++;

            if (informIndices)
            {
                OnTreeAfterCreate(tempVoxelIndices);
            }

            int refreshChunksCount = treeChunkRefreshRequests.Count;

            for (int k = 0; k < refreshChunksCount; k++)
            {
                ChunkRequestRefresh(treeChunkRefreshRequests [k], false, true);
            }
        }
        void ModelPlace(Vector3 position, ModelDefinition model, ref Bounds bounds, int rotationDegrees = 0, float colorBrightness = 1f, bool fitTerrain = false, List <VoxelIndex> indices = null, int indexStart = -1, int indexEnd = -1)
        {
            if (model == null)
            {
                return;
            }
            if (indexStart < 0)
            {
                indexStart = 0;
            }
            if (indexEnd < 0)
            {
                indexEnd = model.bits.Length - 1;
            }

            Vector3 pos;
            int     modelOneYRow = model.sizeZ * model.sizeX;
            int     modelOneZRow = model.sizeX;
            int     halfSizeX    = model.sizeX / 2;
            int     halfSizeZ    = model.sizeZ / 2;

            if (rotationDegrees == 360)
            {
                switch (UnityEngine.Random.Range(0, 4))
                {
                case 0:
                    rotationDegrees = 90;
                    break;

                case 1:
                    rotationDegrees = 180;
                    break;

                case 2:
                    rotationDegrees = 270;
                    break;
                }
            }

            bool indicesProvided = indices != null;

            if (indicesProvided && indexStart < 0 && indexEnd < 0)
            {
                indices.Clear();
            }
            VoxelIndex index     = new VoxelIndex();
            VoxelChunk lastChunk = null;
            int        tmp;
            Vector3    min = bounds.min;
            Vector3    max = bounds.max;

            for (int b = indexStart; b <= indexEnd; b++)
            {
                int bitIndex = model.bits [b].voxelIndex;
                int py       = bitIndex / modelOneYRow;
                int remy     = bitIndex - py * modelOneYRow;
                int pz       = remy / modelOneZRow;
                int px       = remy - pz * modelOneZRow;
                switch (rotationDegrees)
                {
                case 90:
                    tmp = px;
                    px  = halfSizeZ - pz;
                    pz  = halfSizeX - tmp;
                    break;

                case 180:
                    px = halfSizeX - px;
                    pz = halfSizeZ - pz;
                    break;

                case 270:
                    tmp = px;
                    px  = pz - halfSizeZ;
                    pz  = tmp - halfSizeX;
                    break;

                default:
                    px -= halfSizeX;
                    pz -= halfSizeZ;
                    break;
                }

                pos.x = position.x + model.offsetX + px;
                pos.y = position.y + model.offsetY + py;
                pos.z = position.z + model.offsetZ + pz;

                VoxelChunk chunk;
                int        voxelIndex;
                if (GetVoxelIndex(pos, out chunk, out voxelIndex))
                {
                    Color32         color      = model.bits [b].finalColor;
                    VoxelDefinition vd         = model.bits [b].voxelDefinition ?? defaultVoxel;
                    bool            emptyVoxel = model.bits [b].isEmpty;
                    if (emptyVoxel)
                    {
                        chunk.voxels [voxelIndex] = Voxel.Empty;
                    }
                    else
                    {
                        if (colorBrightness != 1f)
                        {
                            color.r = (byte)(color.r * colorBrightness);
                            color.g = (byte)(color.g * colorBrightness);
                            color.b = (byte)(color.b * colorBrightness);
                        }
                        chunk.voxels [voxelIndex].Set(vd, color);
                        // Add index
                        if (indicesProvided)
                        {
                            index.chunk      = chunk;
                            index.voxelIndex = voxelIndex;
                            index.position   = pos;
                            indices.Add(index);
                        }
                        if (pos.x < min.x)
                        {
                            min.x = pos.x;
                        }
                        if (pos.y < min.y)
                        {
                            min.y = pos.y;
                        }
                        if (pos.z < min.z)
                        {
                            min.z = pos.z;
                        }
                        if (pos.x > max.x)
                        {
                            max.x = pos.x;
                        }
                        if (pos.y > max.y)
                        {
                            max.y = pos.y;
                        }
                        if (pos.z > max.z)
                        {
                            max.z = pos.z;
                        }
                    }

                    // Prevent tree population
                    chunk.allowTrees = false;
                    chunk.modified   = true;

                    if (fitTerrain && !emptyVoxel)
                    {
                        // Fill beneath row 1
                        if (py == 0)
                        {
                            Vector3 under = pos;
                            under.y -= 1;
                            for (int k = 0; k < 100; k++, under.y--)
                            {
                                VoxelChunk lowChunk;
                                int        vindex;
                                GetVoxelIndex(under, out lowChunk, out vindex, false);
                                if (lowChunk != null && lowChunk.voxels [vindex].opaque < FULL_OPAQUE)
                                {
                                    lowChunk.voxels [vindex].Set(vd, color);
                                    if (lowChunk != lastChunk)
                                    {
                                        lastChunk = lowChunk;
                                        if (!lastChunk.inqueue)
                                        {
                                            ChunkRequestRefresh(lastChunk, true, true);
                                        }
                                    }
                                }
                                else
                                {
                                    break;
                                }
                            }
                        }
                    }

                    if (chunk != lastChunk)
                    {
                        lastChunk = chunk;
                        if (!lastChunk.inqueue)
                        {
                            lastChunk.MarkAsInconclusive();
                            ChunkRequestRefresh(lastChunk, true, true);
                        }
                    }
                }
            }

            FastVector.Floor(ref min);
            FastVector.Ceiling(ref max);
            bounds.center = (max + min) * 0.5f;
            bounds.size   = max - min;
        }
        void ModelPlace(Vector3 position, ModelDefinition model, ref Bounds bounds, int rotationDegrees = 0, float colorBrightness = 1f, bool fitTerrain = false, List <VoxelIndex> indices = null, int indexStart = -1, int indexEnd = -1, bool useUnpopulatedChunks = false, bool refreshChunks = true)
        {
            if (model == null)
            {
                return;
            }
            if (indexStart < 0)
            {
                indexStart = 0;
            }
            if (indexEnd < 0)
            {
                indexEnd = model.bits.Length - 1;
            }

            Vector3 pos;
            int     modelOneYRow = model.sizeZ * model.sizeX;
            int     modelOneZRow = model.sizeX;

            if (rotationDegrees == 360)
            {
                switch (WorldRand.Range(0, 4))
                {
                case 1:
                    rotationDegrees = 90;
                    break;

                case 2:
                    rotationDegrees = 180;
                    break;

                case 3:
                    rotationDegrees = 270;
                    break;
                }
            }

            int     halfSizeX = model.sizeX / 2;
            int     halfSizeZ = model.sizeZ / 2;
            Vector3 zeroPos   = Quaternion.Euler(0, rotationDegrees, 0) * new Vector3(-halfSizeX, 0, -halfSizeZ);

            // ensure all voxel definitions are present
            //bool reloadTextures = false;
            for (int b = indexStart; b <= indexEnd; b++)
            {
                VoxelDefinition vd = model.bits [b].voxelDefinition;
                if (vd != null && vd.index == 0)
                {
                    AddVoxelDefinition(vd);
                    //reloadTextures = true;
                }
            }
            //if (reloadTextures) { // TODO: RML (AddVoxelDefinition already marks reload world textures flag)
            //    LoadWorldTextures();
            //}

            bool indicesProvided = indices != null;

            if (indicesProvided && indexStart < 0 && indexEnd < 0)
            {
                indices.Clear();
            }
            VoxelIndex index = new VoxelIndex();
            Vector3    min   = bounds.min;
            Vector3    max   = bounds.max;

            for (int b = indexStart; b <= indexEnd; b++)
            {
                int bitIndex = model.bits [b].voxelIndex;
                int py       = bitIndex / modelOneYRow;
                int remy     = bitIndex - py * modelOneYRow;
                int pz       = remy / modelOneZRow;
                int px       = remy - pz * modelOneZRow;

                float wx = zeroPos.x, wz = zeroPos.z;
                switch (rotationDegrees)
                {
                case 90:
                    wx += pz;
                    wz -= px;
                    break;

                case 180:
                    wx -= px;
                    wz -= pz;
                    break;

                case 270:
                    wx -= pz;
                    wz += px;
                    break;

                default:
                    wx += px;
                    wz += pz;
                    break;
                }

                pos.x = position.x + model.offsetX + wx;
                pos.y = position.y + model.offsetY + py;
                pos.z = position.z + model.offsetZ + wz;

                VoxelChunk chunk;
                int        voxelIndex;
                if (useUnpopulatedChunks)
                {
                    chunk = GetChunkUnpopulated(pos);
                }
                if (GetVoxelIndex(pos, out chunk, out voxelIndex))
                {
                    bool emptyVoxel = model.bits [b].isEmpty;
                    if (emptyVoxel)
                    {
                        chunk.voxels [voxelIndex] = Voxel.Hole;
                    }
                    else
                    {
                        Color32 color = model.bits [b].finalColor;
                        if (colorBrightness != 1f)
                        {
                            color.r = (byte)(color.r * colorBrightness);
                            color.g = (byte)(color.g * colorBrightness);
                            color.b = (byte)(color.b * colorBrightness);
                        }
                        VoxelDefinition vd = model.bits [b].voxelDefinition ?? defaultVoxel;
                        chunk.voxels [voxelIndex].Set(vd, color);
                        float rotation = (model.bits [b].rotation + 360 + rotationDegrees) % 360;
                        if (rotation != 0)
                        {
                            chunk.voxels [voxelIndex].SetTextureRotation(Voxel.GetTextureRotationFromDegrees(rotation));
                        }

                        // Add index
                        if (indicesProvided)
                        {
                            index.chunk      = chunk;
                            index.voxelIndex = voxelIndex;
                            index.position   = pos;
                            indices.Add(index);
                        }
                        if (pos.x < min.x)
                        {
                            min.x = pos.x;
                        }
                        if (pos.y < min.y)
                        {
                            min.y = pos.y;
                        }
                        if (pos.z < min.z)
                        {
                            min.z = pos.z;
                        }
                        if (pos.x > max.x)
                        {
                            max.x = pos.x;
                        }
                        if (pos.y > max.y)
                        {
                            max.y = pos.y;
                        }
                        if (pos.z > max.z)
                        {
                            max.z = pos.z;
                        }

                        if (fitTerrain)
                        {
                            // Fill beneath row 1
                            if (py == 0)
                            {
                                Vector3 under = pos;
                                under.y -= 1;
                                for (int k = 0; k < 100; k++, under.y--)
                                {
                                    VoxelChunk lowChunk;
                                    int        vindex;
                                    GetVoxelIndex(under, out lowChunk, out vindex, false);
                                    if (lowChunk != null && lowChunk.voxels [vindex].opaque < FULL_OPAQUE)
                                    {
                                        lowChunk.voxels [vindex].Set(vd, color);
                                        lowChunk.modified = true;
                                        if (!lowChunk.inqueue && !useUnpopulatedChunks)
                                        {
                                            ChunkRequestRefresh(lowChunk, true, true);
                                        }
                                    }
                                    else
                                    {
                                        break;
                                    }
                                }
                            }
                        }
                    }

                    // Prevent tree population
                    chunk.allowTrees = false;
                    chunk.modified   = true;

                    if (!chunk.inqueue && !useUnpopulatedChunks)
                    {
                        chunk.MarkAsInconclusive();
                        if (refreshChunks)
                        {
                            ChunkRequestRefresh(chunk, true, true);
                        }
                    }
                }
            }

            FastVector.Floor(ref min);
            FastVector.Ceiling(ref max);
            bounds.center = (max + min) * 0.5f;
            bounds.size   = max - min;
        }