Author Topic: A combination of multiple questions that has been keeping me wondering  (Read 1233 times)

I am just spitballing trying to remember all of this so bear with me and if i am not clear enough, just specify.
 How do you target all players?
 What is the best way to make a counter for seconds/minutes/custom value of time, have it loop, call for number of loops so far etc.?
 What is the best way to save and call for custom preferences for clients. For example saving various scores of a client for a gamemode without fileObjects?
 How do classes work? I am quite stumped on this subject and it seems very very important.

Help would be appreciated.

How do you target all players?
I'm not exactly sure what you mean by "target." Blockland doesn't really have a 'targetting' function. I assume you're asking how to get every player on the server though, which is pretty easy:

for(%i = 0; %i < ClientGroup.getCount(); %i++) {
    %client = ClientGroup.getObject(%i);
    messageClient(%client, '', "You have been targeted!");
}


What is the best way to make a counter, have it loop, call for number of loops so far, etc.
There's two ways to do this, the accurate way and the inaccurate way. First I'll start with the inaccurate way because it's simpler.

There is a function called schedule that allows you to delay the calling of a function. You can easily make a counter by making a function that increases a variable, then using schedule to call itself again after a second.

function counterIncrease() {
    $CounterValue++;
    schedule(1000, 0, counterIncrease);
}


The arguments for schedule are time (in millseconds, 1000 ms is a second), ignore the second one (always 0), the function to call, then any arguments to call the function with come after that. The issue with schedules are that they're not 100% accurate. They're apt to be off by a number of milliseconds, and this means that over the course of a day or so your counter can become significantly off from the real amount of time that's passed. The best way to get around this is to calculate the actual time that's passed, and just use schedule to keep calling the function.

function counterIncrease(%lastTime) {
    %thisTime = getSimTime();

    if(%lastTime == 0)
        %lastTime = %thisTime;

    if(%thisTime - %lastTime > 1000) {
        %secondsPassed = mFloor((%thisTime - %lastTime)/1000);
        $CounterValue += %secondsPassed;
        %lastTime += 1000 * %secondsPassed;
    }

    schedule(500, 0, counterIncrease, %lastTime);
}


I decreased the schedule to 500ms in this one so that it's impossible for a number to be skipped due to poor timing. This one works by calling the function every 500ms with the last time that the counter increased, then when it's been at least a second since the last time the counter increased, it updates the last time that the counter increased by exactly the amount of seconds that have passed, then increases the counter by the amount of seconds that have passed. This way it doesn't matter if schedule isn't perfect, and if it lags for more than a second it'll update by more than a second.

What is the best way to save and call for custom preferences for clients?
Ah, the old data storage dilemma. There's been a lot of thought put into this one both inside and outside of Blockland. Unfortunately Blockland is pretty stuffty at this. Your best bet is to create a script object every time a player leaves, copy all the important data into it, then save that script object. So, something like this:

Code: [Select]
package saveScores {
    function GameConnection::onClientLeaveGame(%this) {
        %saveObj = new ScriptObject(%this.getBLID() @ "_saveObj");
        %saveObj.name = %this.getPlayerName();
        %saveObj.BL_ID = %this.getBL_ID();
        %saveObj.score = %this.score;
        %saveObj.position = %this.getPosition();
        //whatever else you want to save
        %saveObj.save("config/players/" @ %saveObj.BL_ID @ ".cs");
        %saveObj.delete();
        parent::onClientLeaveGame(%this);
    }
};
activatePackage(saveScores);

Then, to load it, just do the opposite:

Code: [Select]
package loadScores {
    function GameConnection::onClientEnterGame(%this) {
        exec("config/players/" @ %this.getBLID() @ ".cs");
        %saveObj = (%this.getBLID() @ "_saveObj");
        %this.score = %saveObj.score;
        %this.setTransform(%saveObj.position);
        %saveObj.delete();
        parent::onClientEnterGame(%this);
    }
};
activatePackage(loadScores);

By the way, those can both be put into one package.

How do classes work?
Classes are actually pretty unimportant in Torque. They're super easy though.

Code: [Select]
function MyClass::sayHello(%this) {
    messageAll('', "Hello World!");
    return %this;
}

new ScriptObject() {
    class = MyClass;
}.sayHello().delete();

You can also use pseudo-classes by using the name of an object.

Code: [Select]
function MyObject::sayHello(%this) {
    messageAll('', "Hello World!");
    return %this;
}

new ScriptObject(MyObject).sayHello().delete();
« Last Edit: November 06, 2014, 01:51:57 PM by $trinick »

Re: What is the best way to save and call for custom preferences for clients?

Trinick's method is good, but if you only want to save one value, like score, you can create a single ScriptObject, place everybody's scores into it (like myObject.score[11902] = 42), and then save it when the server shuts down.

Re: What is the best way to save and call for custom preferences for clients?

Trinick's method is good, but if you only want to save one value, like score, you can create a single ScriptObject, place everybody's scores into it (like myObject.score[11902] = 42), and then save it when the server shuts down.

Mmhmm, I thought about posting that one too. The only issue with this is if the server stays up for a long time (or it's reloaded every time the server starts up, resulting in old data never being cleared) you can end up with tens of thousands of entries on this script object. If you're only saving it every time the server shuts down it's not too big of a deal, but it takes a second to save that much data to a file and the server will lag while it saves.

Mmhmm, I thought about posting that one too. The only issue with this is if the server stays up for a long time (or it's reloaded every time the server starts up, resulting in old data never being cleared) you can end up with tens of thousands of entries on this script object. If you're only saving it every time the server shuts down it's not too big of a deal, but it takes a second to save that much data to a file and the server will lag while it saves.

On the flip side, saving single values to individual files will, in essence, make the score variable take up 4096 bytes.

So either you have tens of thousands of individual files, taking up countable megabytes; or you have one file, taking up countable processing time.  This is known as a space-time tradeoff.

If you want to have both a fast and compact save file, the only way is to ditch the scripting method and use a text file.  Compilation is extremely slow compared to any sane loading function.  The only problem is that then you have to either read the whole text file into memory, or read it every time anyone spawns.  Again, space-time tradeoff.