Roll20 uses cookies to improve your experience on our site. Cookies enable you to enjoy certain features, social sharing functionality, and tailor message and display ads to your interests on our site and others. They also help us understand how our site is being used. By continuing to use our site, you consent to our use of cookies. Update your cookie preferences .
×
Create a free account

[ERROR] Cannot read property 'split' of undefined

December 28 (7 years ago)

Edited December 28 (7 years ago)
Missingquery
Pro
Sheet Author
API Scripter
I get the error in the title when I run the script, but I'm not sure what's returning the error, since it's occuring in the updateStatusMarker protocol and thus obscured from view. Here is my code, if that helps:
on('chat:message', function(msg) {
    if (msg.type != 'api') return;
    var parts = msg.content.split(' ');
    var command = parts.shift().substring(1);
    if (command == 'staff') {
        if (parts.length < 2) {
            sendChat('SYSTEM', 'You must provide a selected token id and a target token id.');
            return;
        }
        var selectedId = parts[0];
        var targetId = parts[1];
        var selectedToken = getObj('graphic', selectedId);
        var targetToken = getObj('graphic', targetId);

        if (!selectedToken) {
            sendChat('SYSTEM', 'Selected token id not provided.');
            return;
        }
        if (!targetToken) {
            sendChat('SYSTEM', 'Target token id not provided.');
            return;
        }
        var who = getObj('character', selectedToken.get('represents'));
        if (!who) {
            who = selectedToken.get('name');
        } else {
            who = 'character|' + who.id;
        }

        var staffer = getObj('character', selectedToken.get('represents'));
        var target = getObj('character', targetToken.get('represents'));

	//...objects and stats; I don't think any of these are causing the error and seem to be perfectly fine
	//They're referenced elsewhere in the code, though, so I wouldn't recommend running it anywhere

	//example object
	const Silence = {
            name : "Silence",
            type : "status",
            target: [Magbd],
            effect : Number(MagB.get("current")) * -1,
            status: "status_interdiction",
            chatmsg: targetToken.get("name") + " cannot use magic for the next turn!"
        };

	//list of objects
	const staveslist = [Heal,Mend,Physic,Recover,Fortify,Bloom_Festal,Sun_Festal,Wane_Festal,Moon_Festal,Great_Festal,Freeze,Enfeeble,Entrap,Rescue,Silence,Hexing_Rod];

	//I'm pretty sure the error occurs somewhere here
        if (WTypeA != "Staves/Rods"){
            chatstr += "\n Weapon is not a staff!"
        } else {
            for (var i in staveslist){
                if (staveslist[i].name == WNameA){
                    j = staveslist[i];
                    //check for range
                    if (((Range1A) <= (diff/70)) && ((diff/70) <= (Range2A))){
                        if (j.type == "healing"){
                            //Set with workers in respect to total caps
                            HPVal = Number(CurrHPB.get("current")) + j.effect
                            CurrHPB.setWithWorker({current: HPVal})
                            chatstr += "\n" + targetToken.get("name") + " is healed for " + String(j.effect) + " HP!"
                        }
                        if (j.type == "status"){
                            for (var a in j.target){
                                j.target[a].setWithWorker("current",j.effect)
                            }
                            target.set(j.status);
                            chatstr += j.chatmsg
                        }
                    } else {
                        chatstr += "\n Staff is not in range!"
                    }
                }
            }
        }
        sendChat(who, chatstr);
December 28 (7 years ago)

Edited December 28 (7 years ago)
GiGs
Pro
Sheet Author
API Scripter
On thing I notice:
if (WTypeA != "Staves/Rods"){
WTypeA isnt defined anywhere in the code.

Also, when you really arent sure what isn't working, a good way is to enter an early "return" statement, and put some log statements before that to make sure variables are being set properly.

Like so:
on('chat:message', function(msg) {
    if (msg.type != 'api') return;
    var parts = msg.content.split(' ');
    var command = parts.shift().substring(1);
    log("Command: " + command);
    if (command == 'staff') {
    return; // put this anyway, to ensure the macro stops before it reaches the error.
The above is just an example - experiment where to put return in the code. As long as you dont get an error, you know everything is working fine up to that point. Then when you trigger the error, put return just before that, and use log statements to check your variables are initialised and have the values you expect them to.
December 28 (7 years ago)
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
Can you post the full error you get? That would help with figuring out what is going on.
December 28 (7 years ago)

Edited December 28 (7 years ago)
Missingquery
Pro
Sheet Author
API Scripter
WTypeA is one of the variables defined in the omitted 'objects and variables' section. I'll try adding some log statements and see what happens.
Edit: The full error is
TypeError: Cannot read property 'split' of undefined
TypeError: Cannot read property 'split' of undefined
    at updateStatusMarker (/home/node/d20-api-server/api.js:1943:53)
    at TrackedObj._validateAttrs (/home/node/d20-api-server/api.js:828:17)
    at TrackedObj.set (/home/node/d20-api-server/api.js:858:18)
    at apiscript.js:950:36
    at eval (eval at <anonymous> (/home/node/d20-api-server/api.js:146:1), <anonymous>:65:16)
    at Object.publish (eval at <anonymous> (/home/node/d20-api-server/api.js:146:1), <anonymous>:70:8)
    at /home/node/d20-api-server/api.js:1510:12
    at /home/node/d20-api-server/node_modules/firebase/lib/firebase-node.js:93:560
    at hc (/home/node/d20-api-server/node_modules/firebase/lib/firebase-node.js:39:147)
    at Kd (/home/node/d20-api-server/node_modules/firebase/lib/firebase-node.js:93:546)
December 28 (7 years ago)

Edited December 28 (7 years ago)
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
Hmm, I may just not be following your code properly, but I see several issues.

In your section that you think is the problem:
	const staveslist = [Heal,Mend,Physic,Recover,Fortify,Bloom_Festal,Sun_Festal,Wane_Festal,Moon_Festal,Great_Festal,Freeze,Enfeeble,Entrap,Rescue,Silence,Hexing_Rod];
	
	//I'm pretty sure the error occurs somewhere here
        if (WTypeA != "Staves/Rods"){
            chatstr += "\n Weapon is not a staff!"
        } else {
            for (var i in staveslist){
                if (staveslist[i].name == WNameA){ /*I'd recommend changing to using "===" for your equivalency checks. This is a good explanation of abstract vs strict equality.
							I think that this equivalency issue may be the cause of your problem, because your if statements aren't actually evaluating as you think they are
Also, as with your j variable below, staveslist[i] is not an object, and so doesn't actually have a name property*/
                    j = staveslist[i]; //This looks like it just evaluates to a string from the staveslist array                     //check for range                     if (((Range1A) <= (diff/70)) && ((diff/70) <= (Range2A))){                         if (j.type == "healing"){ //Because j evaluates to a string, how can you reference it as an object?                             //Set with workers in respect to total caps                             HPVal = Number(CurrHPB.get("current")) + j.effect //Same thing here                             CurrHPB.setWithWorker({current: HPVal})                             chatstr += "\n" + targetToken.get("name") + " is healed for " + String(j.effect) + " HP!"                         }                         if (j.type == "status"){ //Same thing here                             for (var a in j.target){ //And here                                 j.target[a].setWithWorker("current",j.effect) //And here                             }                             target.set(j.status); //And here                             chatstr += j.chatmsg //And here                         }                     } else {                         chatstr += "\n Staff is not in range!"                     }                 }             }         }
I'm not sure if any of that is causing your issue, but one thing I notice about your statusmarker setting is that I can't see where you are creating an object in the form {statusmarkers:"string of statsumarkers"}. This would prevent statusmarkers from being set.

Hope that helps,

Scott
December 28 (7 years ago)

Edited December 28 (7 years ago)
Missingquery
Pro
Sheet Author
API Scripter
The staveslist array is full of objects, not strings, like the Silence object. I've had no problems with the script working when j.type == "healing"; it's just when it's "status" that I run into these problems, so it's able to detect the difference. Changing '==' to '===' doesn't seem to affect the error, either. As for this:
one thing I notice about your statusmarker setting is that I can't see where you are creating an object in the form {statusmarkers:"string of statsumarkers"}
I do actually have that here:
	const Silence = {
            name : "Silence",
            type : "status",
            target: [Magbd],
            effect : Number(MagB.get("current")) * -1,
            status: "status_interdiction",
            chatmsg: targetToken.get("name") + " cannot use magic for the next turn!"
        };
So I guess I'm still not really sure what the problem is.
December 28 (7 years ago)

Edited December 28 (7 years ago)
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
Ah, ok, Missed that that was an array of constants, not strings.

So, we're missing quite a bit of code then.

However, in your example object of silence, you have defined the statusmarkers incorrectly for proper setting:

Statusmarkers can be interacted in two different ways.(See the section on statusmarkers)
  1. By accessing the statusmarkers property directly
    1. obj.get('statusmarkers') => comma delimited list of statusmarkers
    2. obj.set({statusmarkers:"interdiction,shield,etc"})
  2. By accessing/setting the specific statusmarker
    1. obj.get('status_red') => false/true/number;
    2. obj.set({status_red:true}) or obj.set({status_red:2})
What your obj.set expression looks like if you sub in the variable values is this:

obj.set(j.status) which becomes (in the case of your silence example) obj.set("status_interdiction").

You aren't actually setting the property to anything which is probably what is causing the error in applystatusmarkers. You need to change your objects to this (using the silence example):
	const Silence = {
            name : "Silence",
            type : "status",
            target: [Magbd],
            effect : Number(MagB.get("current")) * -1,
            status: {status_interdiction:true},
            chatmsg: targetToken.get("name") + " cannot use magic for the next turn!"
        };

December 28 (7 years ago)

Edited December 28 (7 years ago)
Missingquery
Pro
Sheet Author
API Scripter
Alright, that seems to have solved it. Thank you!
Edit: I have one more question, actually. In interacting with specific markers, how would I set a status with a hyphenated name, such as:
status: {status_back-pain: 4}
Since the - is interpreted as a minus, not being in a string, the console throws an error but I'm not sure how to list the status name in a way that the API would recognize.
December 28 (7 years ago)
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
Happy rolling
December 28 (7 years ago)
GiGs
Pro
Sheet Author
API Scripter

Marth Lowell said:

Alright, that seems to have solved it. Thank you!
Edit: I have one more question, actually. In interacting with specific markers, how would I set a status with a hyphenated name, such as:
status: {status_back-pain: 4}
Since the - is interpreted as a minus, not being in a string, the console throws an error but I'm not sure how to list the status name in a way that the API would recognize.
Have you tried enclosing it in quotes, like
status: {"status_back-pain": 4}

December 28 (7 years ago)
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator

G G said:

Marth Lowell said:

Alright, that seems to have solved it. Thank you!
Edit: I have one more question, actually. In interacting with specific markers, how would I set a status with a hyphenated name, such as:
status: {status_back-pain: 4}
Since the - is interpreted as a minus, not being in a string, the console throws an error but I'm not sure how to list the status name in a way that the API would recognize.
Have you tried enclosing it in quotes, like
status: {"status_back-pain": 4}


Yep, this is how you do that