Author Topic: [Help] Leveling System, Code on Spawn, Schedules, Teleportation  (Read 5080 times)

Hey, so I'm trying to make a game where you kill bots and then you get points and level up, ect.
I have a goal of getting different classes, but for now I'm just working with one.
Anyways, I wrote this script as kind of an idea of what I'm getting at:

function servercmdLevelUp(%client)
{
    if(%client.pts >= 100)
    {
        %client.level = %client.level + 1;
        %client.damagemult = %client.damagemult +0.2;
        %client.pts = %client.pts - 100;
    }
}

Now, this would be a command, and when someone has 100 points (not the minigame kind) they can execute it. If their amount of points is great enough, it would add one to their level count along with 0.2 to their damage multiplier (default 1). It also subtracts 100 points so you can't buy another level off the same points.

The problem with this, obviously, is they are just variables. Well, %client.level is actually fine as is, maybe having a HUD display its value. But is it possible to get a damage multiplier going? I frankly have no idea how to do that. If it's not possible, that's okay. Also, am I able to auto-detect when a player's score hits 100? I figured that running something every second would get spammy. If this function makes no actual sense in torquescript whatsoever, tell me. I'll fix it.

PS: I figured out a way to store these variables, don't worry.

To rephrase my questions:

1. Is it possible to get a damage multiplier working, where the more your multiplier is the more damage is done across all weapons. If this is not possible/too painstaking, it's fine.

2. Is it possible to autodetect when a variable hits a certain amount without spamming the server? Maybe checking every 30 seconds? (the variable in this case being %client.pts

3. Does my script make sense in torque? I'm kinda in uncharted territory.

4. How would I make it so I add to a variable every time I kill a bot? I'd imagine it has to do with modifying some default function, just not exactly sure what in this case. OR maybe, if easier, every time someone is killed the player gets his points upped.
« Last Edit: April 11, 2015, 06:30:27 PM by Johnny Blockhead »

1. Yes, use trace and see which function gets called when damage is dealt and package it.

2. Yes, you shouldn't need a loop to achieve this. Simply check the value every time the variable is modified.

3. Syntactically, yes it does.

4. See step 1.

2. Yes, you shouldn't need a loop to achieve this. Simply check the value every time the variable is modified.
More info: do the check wherever your adding to pts
herp
« Last Edit: April 06, 2015, 10:57:54 PM by Headcrab Zombie »

More info: do the check wherever your adding to pts

u wot m(18/2)-1 ? Isn't that what i just said? Lol.

u wot m(18/2)-1 ? Isn't that what i just said? Lol.
...yes, apparently i didn't read it

You can make functions add the variables, that way it could be easier in the future.

function GameConnection::addStuff(%this,%stuff)
{
   %this.stuff += %stuff;
   return %this.stuff;
}

//Kind of pointless since you can just do %this.stuff, but at least you can't mod the variable with doing %client.stuff();
function GameConnection::stuff(%this)
{
   return %this.stuff;
}

Thanks everyone for simply responding!
package test
{
    function servercmdPlayer::PlayDeathAnimation(%client)
    {
        talk("Psst. It's working");
        echo("This is for the previous thing is broken.");
    }
};
activatePackage(test);

This is the code I'm using for the bot death thing, but I simply cannot get it to work. I've probably tried ten different things now, from fxDTSBrick::OnBotDeath to Player::playDeathCry. It's not working. Is something wrong with my script? I beleive for a second I got it to work, but I can't replicate that despite executing every revision of the code. I'm sure the package is activating, since I put another test function inside the package and it worked.

Any ideas?

Also, I'll definitely use that, Visolator.
Edit: gameConnection::onDeath works, but not on bots.
Edit 2: I'm dumb. It's working, I had to remove the servercmd part.
Edit 3: Here's my current code
package test
{
    function fxDTSBrick::OnBotDeath(%client) //executes twice for some reason, whatever.
    {
        talk("The death thing is working, Mr. Jones.");
    }
};
activatePackage(test);

Whenever a bot dies though, no death animation occurs. I feel like I'm overwriting something, is there a thing I should be doing?
Edit 4: Okay, I have what I feel like the last question is. Now that this is the trillionth edit, I'll just do the numbers thing again:

1. When a bot dies, the body doesn't go away. Its just the bot standing in the default position, and I can walk into it. This is when I run the script. How do I fix this?
2. How'd I make a client command to display what their level variable (ect) is? I know how to, its just that I'd have to use the %client command to figure out who's asking, and then display a global variable off of that. So, in my mind it'd look something like %client.$level. How would I do this?
« Last Edit: April 06, 2015, 11:55:07 PM by Johnny Blockhead »

The first function I can't tell what you want to do.
If you want something that's called when you type /playdeathanimation, the function name should just be serverCmdPlayDeathAnimation
If that's not what you want, then I don't know what you want


For the second function
fxDtsBrick::onBotDeath.....might be the correct function for bots spawned through events. But that's the only bots it would work for.
The %client arguments isn't pointing to a client (you can technically name it whatever you like, but you should name it what it's actually describing so you know what's going on)
In a method (a function called on an object, named in the format className::functionName) the first argument is always be the object it's called on and is typically named %this. So, in this example, since it's an fxDtsBrick,  the first argument is the brick that it's called on



Your questions:
1. You need to call the parent. Insert Parent::onBotDeath(%this); in the function. This calls the original version of the function.
(The argument name %this assumes you renamed the %client to %this)
2. A function with a name beginning with serverCmd, a messageAll call, and a reference to the level variable that you already have correctly used in your first post

You can also package Armor::Damage as well to check if it is a bot, and then after the parent check if it is dead, and if it says yes, then you can put your code stuff there.

The first function I can't tell what you want to do.
If you want something that's called when you type /playdeathanimation, the function name should just be serverCmdPlayDeathAnimation
If that's not what you want, then I don't know what you want
I was doing servercmd at first, but that was breaking my code. I'm modifying the functions that play on death, not making a slash command.

For the second function
fxDtsBrick::onBotDeath.....might be the correct function for bots spawned through events. But that's the only bots it would work for.
The %client arguments isn't pointing to a client (you can technically name it whatever you like, but you should name it what it's actually describing so you know what's going on)
In a method (a function called on an object, named in the format className::functionName) the first argument is always be the object it's called on and is typically named %this. So, in this example, since it's an fxDtsBrick,  the first argument is the brick that it's called on
Thanks, I should've known this. But now, my code actually needs the %client, since it's doing an autocheck for whether you should be levelled up.

2. A function with a name beginning with serverCmd, a messageAll call, and a reference to the level variable that you already have correctly used in your first post
My problem is I don't know how I'd reference a global variable while referring to a local one.
I'm targeting %client, and a variable on this client is the global variable $level.
This doesn't work:

function servercmdStats(%client)
{
    talk("Your Level:" SPC %client.level);
}
I also tried setting %client.level equal to $client.level, and also replacing the %client.level in the talk command with $client.level. Neither work, spit out nothing. I tried defining level as a thing, still nothing. (this means it isnt a problem with the leveling system)
You can also package Armor::Damage as well to check if it is a bot, and then after the parent check if it is dead, and if it says yes, then you can put your code stuff there.
Cool, I'll look into it. I might just want it so if you kill anything at all, you still get rewarded. Checking if it is dead would be good, though.

Current Code:
package elite
{
    function fxDTSBrick::OnBotDeath(%client, %this) //executes twice for some reason, whatever.
    {
        %client.pts = %client.pts + 1;
        if(%client.pts >= 10)
        {
            $client.level = $client.level + 1;
            $client.damagemult = $client.damagemult +0.2;
            $client.pts = $client.pts - 100;
        }
        Parent::onBotDeath(%this);
    }
};
« Last Edit: April 07, 2015, 01:16:51 AM by Johnny Blockhead »

My problem is I don't know how I'd reference a global variable while referring to a local one.
This doesn't make any sense. The variable is either $level or %client.level. $client.level would attempt to access the level attribute of $client (an object), which I assume you are not defining. Just use %client.level in all cases, and it should do what you want it to do.

The usual thing to package for detecting the death of a player (including the death of a bot) is armor::onDisabled. player::damage would probably work better here, though.

EDIT: As Headcrab Zombie pointed out, the %client in the function you're packaging is a brick, not a client. Further, it would be somewhat obtuse to do what you're trying to do by packaging fxDtsBrick::onBotDeath for a number of reasons.

I suggest packaging AIplayer::damage. The arguments are as follows:
Code: [Select]
AIplayer::damage(%bot, %sourceObject, %damagePosition, %damageAmount, %damageType)After parenting the function, check if the %bot is dead with %bot.getDamagePercent() >= 1. Then you can mess with the %sourceObject's client, which in most cases you will be able to access with %sourceObject.client. You may want to confirm that %sourceObject is not a bot first, just in case you have a bot killing another bot (or itself).
« Last Edit: April 07, 2015, 11:42:09 AM by Amade »

Okay, there are several minor things ill pick up on because nobody else has yet.

%var = %var + 2; is the same as %var += 2; but it looks a lot nicer. There is also -= *= /= which have similar effects.
%var = %var + 1; or %var += 1; is the same as %var++; , it simply increases it by one. You can also use %var--; to decrease it.

And just to confirm, you only need serverCmdXXX in a function when you want players able to do /XXX or if you want a client sided script to talk to a server sided script, but that's a whole other topic.

Edit: gameConnection::onDeath works, but not on bots.

The reason for this is that a GameConnection is a client. Technically, a client is an 'invisible' object which stores information about the people who are connected to the server. When a person connects, a GameConnection is created, and when they leave it is deleted. If a GameConnection is ever deleted, the person who it belongs to is disconnected. A Player object on the other hand is visible, moves around, and is deleted when the player dies (or when they join a minigame, or whatever).
Usually, a client will have a single player, which you can get using %client.player , however you should always check to make sure they're existent (not deleted), by using the isObject(%obj) function. eg if(isObject(%client.player)) { %client.player.kill(); } . You can get a player's client from %player.client but again you should check to make sure they have one, because %player could sometimes be a bot (depends entirely of what you're doing).

I rambled a little, the reason it doesn't work is because bots don't have a client. You want a function for a Player, or an Armor (which is a player datablock, dont worry too much about it, just learn its arguments).
« Last Edit: April 07, 2015, 08:42:15 AM by boodals 2 »

Thanks, I should've known this. But now, my code actually needs the %client, since it's doing an autocheck for whether you should be levelled up.
Naming it %client won't magically make it a client. The first argument will always be the object is called upon (on your case, the brick). A name is just a name. You could name it %cheesePizzaAndBurgers and it would still be a brick. All it does is give you, the programmer, a description of what it is. The scripting engine doesn't care at all.

If you need client, then you need a method that is called on death that takes a client parameter. Just adding client to the arguments doesn't do anything because the code calling it won't be giving it that value


This doesn't work:

function servercmdStats(%client)
{
    talk("Your Level:" SPC %client.level);
}

The only reason for this not to work is if %client.level isn't defined. Make sure your leveling up before you check this
Also, I forgot what talk does. It either sends client side chat messages to server, or announces server side message to everyone. Neither is what you want. You want:
messageclient(%client,'','Your level: %1', %client.level);
« Last Edit: April 07, 2015, 09:53:27 AM by Headcrab Zombie »

Thanks guys! All of these responses are really insightful.
My current code is:
package Experience
{
    function AIplayer::damage(%this, %sourceObject)
    {
        %client = %sourceObject;
        %client.pts += 1;
        if(%client.pts >= 10)
        {
            %client.level += 1;
            %client.pts -= 10;
        }
        parent::damage(%this);
    }

    function servercmdMyStats(%client)
    {
        messageClient(%client, '', "\c5Your Level:" SPC %client.level);
    }
};
activatePackage(Experience);


It is impossible to kill a bot now, and I know it has to due with me not doing this properly:
Your questions:
1. You need to call the parent. Insert Parent::onBotDeath(%this); in the function. This calls the original version of the function.
(The argument name %this assumes you renamed the %client to %this)
The part I think that is causing the problem is highlighted in red. Anyways, I've implemented all of your guy's advice into it, but I'm stumped on how to fix this.

You only parented %this while the function has %sourceObject too.