1. Hey Guest, is it this your first time on the forums?

    Visit the Beginner's Box

    Introduce yourself, read some of the ins and outs of the community, access to useful links and information.

    Dismiss Notice

Auto spawn blobs?

Discussion in 'Modding Help' started by Monkey_Feats, Oct 12, 2014.

  1. Monkey_Feats

    Monkey_Feats Bison Rider Tester

    Messages:
    214
    Hey, I have a conundrum. (because no code ability)

    How would one make an empty tile (constantly) detect the tile left & down from it. Then if the tiles left & down from it are ground tiles, spawn a certain blob..? aka a dirt corner.

    This is my amazing example
    Cheers
    dirt example.png
     
  2. Skinney

    Skinney THD Team THD Team Forum Moderator Tester

    Messages:
    468
    Since you can't attach scripts to tiles, you will most likely want to use a rules script for the timer, checking and spawning. Below is a working example of your request, it iterates through every tile on the map checking for your conditions. If those conditions are found it adds that position to an array, then it will iterate through all those positions and spawn a fishy.

    [​IMG]
    Code:
    // LeftCornerFish.as
    
    const uint tickRate = 10 * getTicksASecond();
    
    void onTick(CRules@ this)
    {
        if (getGameTime() % tickRate == 0)
        {
            print("fishy time!");
    
            CMap@ map = getMap();
            if (map !is null)
            {
                Vec2f[] tiles;
    
                float tileSize = map.tilesize;
    
                uint mapWidth = map.tilemapwidth;
                uint mapHeight = map.tilemapheight;
                uint totalTileSpaces = mapWidth * mapHeight;
    
                for (uint i = 0; i < totalTileSpaces; i++)
                {
                    TileType cent = map.getTile(i).type;
                    TileType down = map.getTile(i + mapWidth).type;
                    TileType left = map.getTile(i - 1).type;
    
                    if (cent == CMap::tile_empty && down == CMap::tile_ground && left == CMap::tile_ground)
                    {
                        Vec2f position = map.getTileWorldPosition(i);
                        tiles.push_back(position);
                    }
                }
    
                for (uint i = 0; i < tiles.length; i++)
                {
                    if (getNet().isServer())
                    {
                        CBlob@ blob = server_CreateBlob("fishy", -1, tiles[i]);
                    }
                }
            }
        }
    }
    Do note this isn't a solution but an example.
     
    norill and Monkey_Feats like this.
  3. Monkey_Feats

    Monkey_Feats Bison Rider Tester

    Messages:
    214
    That's it man, dead fish everywhere now.

    Using a static blob I noticed the script keeps producing blobs on top of one another.
    How to tell it to stop once there is a blob already in the center?
     
  4. Skinney

    Skinney THD Team THD Team Forum Moderator Tester

    Messages:
    468
    Made some minor changes for readability and efficiency, I also added a bool that checks the spawning position for static blobs (note: you can easily expand the conditions of the bool).

    Code:
    // LeftCornerFish.as
    
    const uint tickRate = 10 * getTicksASecond();
    
    void onTick(CRules@ this)
    {
        if (getGameTime() % tickRate == 0)
        {
            print("fishy time!");
    
            CMap@ map = getMap();
            if (map !is null)
            {
                float tileSize = map.tilesize;
    
                uint mapWidth = map.tilemapwidth;
                uint mapHeight = map.tilemapheight;
                uint totalTileSpaces = mapWidth * mapHeight;
    
                for (uint i = 0; i < totalTileSpaces; i++)
                {
                    TileType cent = map.getTile(i).type;
                    TileType down = map.getTile(i + mapWidth).type;
                    TileType left = map.getTile(i - 1).type;
    
                    if (cent == CMap::tile_empty && down == CMap::tile_ground && left == CMap::tile_ground)
                    {
                        Vec2f pos = map.getTileWorldPosition(i) + (Vec2f(tileSize, tileSize) * 0.5f);
                        print("position = " + pos.x + ", " + pos.y);
                        if (getNet().isServer() && canSpawnAtPosition(map, pos))
                        {
                            CBlob@ blob = server_CreateBlob("fishy", -1, pos);
                        }
                    }
                }
            }
        }
    }
    
    bool canSpawnAtPosition(CMap@ map, Vec2f pos)
    {
        CBlob@[] overlapping;
        map.getBlobsAtPosition(pos, @overlapping);
        for (uint i = 0; i < overlapping.length; i++)
        {
            if (overlapping[i].getShape().isStatic())
            {
                return false;
            }
        }
        return true;
    }
     
    Monkey_Feats likes this.
  5. Monkey_Feats

    Monkey_Feats Bison Rider Tester

    Messages:
    214
    Gives me this error ( compile.png )

    What does it mean by "no matching signatures" ?
     
  6. Skinney

    Skinney THD Team THD Team Forum Moderator Tester

    Messages:
    468
    it means that you're trying to call a function that doesn't exit. The function getBlobsAtPosition(Vec2f, CBlob@[]@) is relatively "new", you might want to run forceupdate.bat to ensure you have the latest version of King Arthur's Gold.
     
    Monkey_Feats likes this.
  7. Monkey_Feats

    Monkey_Feats Bison Rider Tester

    Messages:
    214
    Ahh.. my bad...

    One last thing Skinney,

    Is it possible to stop checking the points that have already had a blob placed by the script ?
     
  8. Skinney

    Skinney THD Team THD Team Forum Moderator Tester

    Messages:
    468
    Can you give me some more detail exactly what you want to accomplish, I might be able to come up with a better solution for you.
     
  9. Geti

    Geti Please avoid PMing me (poke a mod instead) THD Team Administrator Global Moderator

    Messages:
    3,730
    @Monkey_Feats: it's going to require an array of bools (true/false values) that is initialised to the size of the map, and all false, and set true each time something is spawned there.

    Code:
    //create and initialise the array (might want to store the array
    //at global scope for easy access, otherwise using rules.set/get)
    //the array is set up to use the same indexing as the tilemap
    //so if we have a tile index (like in skinneys example script),
    //we can use it to check if something has spawned
    CMap@ map = getMap();
    array<bool> has_spawned;
    int tilemapsize = map.tilemapwidth * map.tilemapheight;
    has_spawned.resize(tilemapsize);
    for(int i = 0; i < tilemapsize; i++)
        has_spawned[i] = false;
    
    //using some tile index i, like in skinney's "for (uint i = 0; i < totalTileSpaces; i++)"
    if(!has_spawned[i] && ( /*all your other conditions here*/ ))
    {
        has_spawned[i] = true;
        /*
            do spawning here.
        */
    }
    I've tried to give an example you need to do a bit of piecing together to work with - this is meant to be educational and show you how you'd go about doing that, rather than give you a copy-and-paste solution :)

    glad to see you getting interested in programming/modding.
     
  10. Monkey_Feats

    Monkey_Feats Bison Rider Tester

    Messages:
    214

    Thanks Skinney your a legend!

    In short, I want dirt to always spawn corners (where it can).

    What you have written already is working good.

    However dirt corners respawn if destroyed.
    Also if a corner has anything other than two dirt tiles next to it, It should no longer exist.

    screen-14-10-14-17-00-04.png
    --- Double Post Merged, Oct 14, 2014, Original Post Date: Oct 14, 2014 ---
    @Geti Thanks

    That's the way I rather it anyway. To be honest I am in over my head with this kind question.
    I'm as new to coding as new gets.

    I will read what you wrote there though :B):
     
    Geti likes this.