[SOLVED] room prototype stats problem reading length of hostiles found



  • Update, I have solved the problem by checking if the array returned from the find function is empty, and returning an alternate object if its empty, such as not to access any methods on a undefined element at foes[0] in the event the room has no hostiles.

    SEE MY REPLY FOR UPDATED CODE

    I created a prototype method for the Room object called stats with one of the goals being to find information on current room hostiles.  The problem I am having is my code fails with 'cannot read length property of undefined' which I can't understand why this is happening.  Can someone please help me understand:

    [code]

    module.exports = function(){
    Room.prototype.stats = function(){
    console.log('this room',this);
    var foes = this.find(FIND_HOSTILE_CREEPS, {
    filter: function(object) {
    return object.getActiveBodyparts(ATTACK) == 0;
    }
    });

    return {
    hostiles: foes,
    numHostiles: foes.length,
    hostileUser: foes[0].length
    }
    }
    };

    [/code]

     

    it would seem that foes is undefined, however when i check with a if (foes === undefined) it returns false.  if i do a JSON.stringify(foe); I get what looks  like an empty array []

     

    Help 🙂

     



  • Ok well it looks like ive solved my problem so I wanted to update this post, it seems what was happening was because there were not any hostiles, I was indeed getting a empty array, and then trying to do stuff on an element [0] of an empty array.  Also I somehow mistyped the username code too:

     

    module.exports = function(){
        Room.prototype.stats = function(){

            var foes = this.find(FIND_HOSTILE_CREEPS, {
                filter: function(object) {
                    return object.getActiveBodyparts(ATTACK) == 0;
                }
            });
            
            if (foes.length > 0){
                return {
                    hostiles: foes,
                    numHostiles: foes.length,
                    hostileUser: foes[0].owner.username
                };
            } else {
                return {
                    hostiles: foes,
                    numHostiles: 0,
                    hostileUser: undefined
                }
            }
        }
    };

     

    So my solution was to test for an empty array and return a different object if its empty such that I am not accessing any methods of an undefined which I would have been getting with foes[0]



  • Hi, i'm extremely new to javascript and therefore am probably asking a stupid question, but can you explain how you would call your function from within main?

    So far, I've created a module called 'logs.test' and copied your code into this module.

    from within main I can't seem to work out how to successfully call it and was hoping you could help?

    All I see within the console is "Testing this function: undefined"

     

    [main]

    var Test = require('logs.test');

    module.exports.loop = function () {

        console.log('Testing this function: ' + Test());

    ...

    }

    [/main]

     

    [logs.test]

    module.exports = function(){
    Room.prototype.stats = function(){

    var foes = this.find(FIND_HOSTILE_CREEPS, {
    filter: function(object) {
    return object.getActiveBodyparts(ATTACK) == 0;
    }
    });

    if (foes.length > 0){
    return {
    hostiles: foes,
    numHostiles: foes.length,
    hostileUser: foes[0].owner.username
    };
    } else {
    return {
    hostiles: foes,
    numHostiles: 0,
    hostileUser: undefined
    }
    }
    }
    };

    [/logs.test]



  • Hi Wheasle, Sorry for the delay in responce.  The function I wrote is to be used as a prototype, as such its not meant to be called directly.  The way you would use my code is by doing something like

     

    [main]

    require('logs.test')();

    ...

    var stats = Game.spawns['Spawn1'].room.stats();

    [/main]

     

    The first line I am not assigning to a variable because the import is a function that needs to run immediately in order to register my prototype

    A prototype is a way we can add functionality to objects we did not make.  The game has a room object , all objects have prototypes, the code I wrote registers my custom function with the room object in order to create a new method called stats in this  particular case.  What it does is create a new object for you which has usefull information about your current attacker, in this format:

    {
                    hostiles: foes,
                    numHostiles: foes.length,
                    hostileUser: foes[0].owner.username

    };

    So the idea here by doing something like var stats = Game.spawns['Spawn1'].room.stats(); is we get a new object called stats with three fields populated.  Lets say we have one attacker in your room and its SomeUser, and that person has 5 of their attacking creeps in your room:

    stats.hostiles would be an array of the 5 creeps your enemy has in your room (from what I remember, I havent played in a week)

    stats.numHostiles would be 5

    status.hostileUser would be 'SomeUser'

    Your script now knows that SomeUser has 5 of their creeps with attack body parts inside your room.

    I don't know how well my code works yet, just that its not throwing any errors, I havent had time to check.  I hope that made some sence.  I recomend searching for videos on youtube on the subject of prototypes, there are many good ones out there that explain it well.

     

     

     

     



  • Hi KnackwurstBagel,

    Thanks for this explanation, this has been very detailed and helpful.  I've seen a few of the prototypes around and always tried treating them like a function and therefore could never get them working.  Thanks for steering me in the right direction.

    Cheers.