Author Topic: How do you make vehicles fly?  (Read 1038 times)

I'm trying to make my first add-on (Flying Horse at age 9) but I need help, what is the code to make vehicles fly?

(Oops, sorry, as I started writing this it grew more and more into something closer to a guide to writing an add-on, than any specific code. Hope it works better that way, though, by explaining the "why" behind the code)

(Oh, and with no idea about how much you already know, I wrote it assuming no previous programming knowledge at all, so it might seem overly simplistic in some areas. Then again, that means that just about anyone can learn the basics from it...)


It depends.


One of the better ways to make a vehicle fly is to use a datablock specifically designed for flying vehicles, however, the horse is actually a player (or really, a bot), so that won't be an option.

Probably the easiest thing to do is keep launching it upwards as long as you hold the jump key. Doing so would require learning about datablocks, packaging, and the SomePlayerDatablockOrWhatever::onTrigger function.

Beware, though, it's not an easy place to start, so unless you already have experience working with Blockland add-ons, you might find it a bit too much to learn all at once.

Oh, and, very importantly, you can create a new <some type of datablock>, that is just like <some existing datablock> but different. If you open up the default Jump Jet player, you'll find that all it does is this: (Copied directly from Player_JumpJet.cs as an example)

Code: [Select]
//super human, just enough jet for a big leap
datablock PlayerData(PlayerJumpJet : PlayerStandardArmor)
{
minJetEnergy = 10;
jetEnergyDrain = 10;
canJet = 1;

rechargeRate = 3.0;

uiName = "Jump-Jet Player";
showEnergyBar = false;
};

The "datablock PlayerData(PlayerJumpJet : PlayerStandardArmor)" means "I want to create a new PlayerData datablock. Call it PlayerJumpJet, and make it exactly like PlayerStandardArmor, except for a few teeeny tiny changes...".


So. Flying horse. Well, opening up the horse vehicle, there is a rather large collection of code. Most of it doubtlessly confusing unless you fully understand what you are looking at. Fortunately, I'll spare you the confusion, and point out that the interesting line is
Code: [Select]
datablock PlayerData(HorseArmor)
While there, it is also important to note the
Code: [Select]
uiName = "Horse";since that will certainly need to be changed.


Now, using the earlier "just like that but different" thing, these things can be put together to get

Code: [Select]
datablock PlayerData(FlyingHorseArmor : HorseArmor)
{
    uiName = "Flying Horse!1!!11oneoneeleven"; //No, wait, just use "Flying Horse". Everyone will prefer it better that way.

    //Oh, by the way, in case you didn't know, everything after a //, until the end of the line, is completely ignored!
    //Perfect for leaving notes to yourself.
};

Except there are two problems there... One, you just have an exact copy of the horse, except it has a different name. Two, what happens if someone unchecked the regular horse, but left yours in? Then it wouldn't have the regular horse to copy from, and would have errors!

Fortunately, Ephialtes took the time to ask Kalphiter to explain how to solve that second problem over here.


To fix the first problem, well, there are countless ways to do so, so I'll go over one of the quicker ones, though surely one of the less correct ones.

Why not make holding the jump button keep launching you upwards? Well, there are a few reasons not to (mainly: it's not a smooth motion, it jumps around a bit, especially for other players in multiplayer)

Well, this is somewhat complicated...

Code: [Select]
//You are not expected to understand most of this. If you do, that's great!
//Warning: Dark magic ahead.

function FlyingHorseArmor::onTrigger(%datablock, %player, %triggerNumber, %isTriggered)
{
    parent::::onTrigger(%datablock, %player, %triggerNumber, %isTriggered);
    //The parent:: line means "do what you would normally do", so in this case, "do what a horse would do here"

    if(%triggerNumber == 2) //2 means "jumping". == means "is the thing on the left the same number as the thing on the right"
    {
        if(%isTriggered)
        {
            %datablock.flyLoop(%player);
        }
        else
        {
            cancel(%player.flyLoopSchedule);
        }
    }
}

function FlyingHorseArmor::flyLoop(%datablock, %player)
{
    cancel(%player.flyLoopSchedule);

    %currentVel = %player.getVelocity();
    %newVel = vectorAdd(%currentVel, "0 0 2");

    %player.setVelocity(%newVel);

    %player.flyLoopSchedule = %datablock.schedule(250, "flyLoop", %player);
}


Well, things are looking almost useful! Let's try it out in-game. Uh oh, how do we do that?

Well, all that you really need is a folder in add-ons, let's call it Vehicle_FlyingHorse. Then you create a file in it called description.txt. You can leave it blank for now. Then you need a file called server.cs in there, as well. Now, following what Kalphiter wrote, lets put this in it...
Code: [Select]
%error = ForceRequiredAddOn("Vehicle_Horse");

if(%error == $Error::AddOn_Disabled)
{
   //A bit of a hack:
   //  we just forced the jeep to load, but the user had it disabled
   //  so lets make it so they can't select it
   HorseArmor.uiName = "";
}

if(%error == $Error::AddOn_NotFound)
{
   error("ERROR: Vehicle_FlyingHorse - required add-on Vehicle_Jeep not found");
}
else
{
   exec("./FlyingHorse.cs");
}

Then, still in that folder you just created, add yet another file, and call it FlyingHorse.cs, and then, in it, finally, we can put all that great (or not so great...) code!

Code: [Select]
datablock PlayerData(FlyingHorseArmor : HorseArmor)
{
    uiName = "Flying Horse!1!!11oneoneeleven"; //No, wait, just use "Flying Horse". Everyone will prefer it better that way.

    //Oh, by the way, in case you didn't know, everything after a //, until the end of the line, is completely ignored!
    //Perfect for leaving notes to yourself.
};

//You are not expected to understand most of this. If you do, that's great!
//Warning: Dark magic ahead.

function FlyingHorseArmor::onTrigger(%datablock, %player, %triggerNumber, %isTriggered)
{
    //The parent:: line means "do what you would normally do", so in this case, "do what a horse would do here"
    parent::onTrigger(%datablock, %player, %triggerNumber, %isTriggered);

    if(%triggerNumber == 2) //2 means "jumping". == means "is the thing on the left the same number as the thing on the right"
    {
        if(%isTriggered)
        {
            %datablock.flyLoop(%player);
        }
        else
        {
            cancel(%player.flyLoopSchedule);
        }
    }
}

function FlyingHorseArmor::flyLoop(%datablock, %player)
{
    cancel(%player.flyLoopSchedule);

    %currentVel = %player.getVelocity();
    %newVel = vectorAdd(%currentVel, "0 0 2");

    %player.setVelocity(%newVel);

    %player.flyLoopSchedule = %datablock.schedule(250, "flyLoop", %player);
}


And now, to test it out...


What?!? It didn't work! That horse is only barely jumping higher than normal! You lied. It was supposed to fly.


Well, the thing is, to fly, you need to go up faster than gravity is pulling you down. So, lets go change a few things. First, oops, forgot to correct that name. Nobody likes excessive punctuation, especially when it isn't punctuation...

So, make things nicer by changing
Code: [Select]
    uiName = "Flying Horse!1!!11oneoneeleven"; //No, wait, just use "Flying Horse". Everyone will prefer it better that way.
into

Code: [Select]
    uiName = "Flying Horse";

And now onto the problem of flight. There are two things that can be done, launch the horse up more often, and do it with more force. Lets do both!

Code: [Select]

function FlyingHorseArmor::flyLoop(%datablock, %player)
{
    cancel(%player.flyLoopSchedule);

    %currentVel = %player.getVelocity();
    %newVel = vectorAdd(%currentVel, "0 0 3");

    %player.setVelocity(%newVel);

    %player.flyLoopSchedule = %datablock.schedule(200, "flyLoop", %player);
}

So, 5 times per second rather than four, and going up 3 faster instead of 2 faster. Small change, really. Now, lets see what that did...

Well, that horse sure ain't flying yet, but it seems to be getting close, like it's on the moon. So, lets up it one more time...
Code: [Select]
    %newVel = vectorAdd(%currentVel, "0 0 3");becomes
Code: [Select]
    %newVel = vectorAdd(%currentVel, "0 0 4");
Well, now it jumps to the bedroom roof, and if you hold space, glides down gracefully. But. Not. Good. Enough. So, lets try 5...


Hooray! It works... Of course, there are still a few things that could be improved, and that description.txt is missing a few lines, but hey! A flying horse!

lmao
I'm trying to make my first add-on (Flying Horse at age 9) but I need help, what is the code to make vehicles fly?
Why don't you scare him more. lol

-snip-
Just look at the flying wheeled Jeep code.
It's a default add-on.
You dont need to write a whole ffing guide.

There is no canFly = false; that you can simply change to true;.

The horse is a PlayerData (a bot)
The jeep is a WheeledVehicleData
The flying jeep is a WheeledVehicleData, with modifications so that it generates lift and can propel itself
The magic carpet is a FlyingVehicleData


Additionally, I covered both actually making a horse fly, AND the process of developing an add-on, all the while trying to keep the concepts relatively simple. Think of it more "How to write an add-on, using a flying horse as an example".


Now, this style might not appeal to some (or even most) people, so if you don't like it, that's just fine! On the other hand, if you enjoyed it, or better yet, learned something from it, great!

In my opinion, it's more important to teach someone how to solve problems in general when they are starting to learn to code add-ons, than how to make it work a specific way that only applies to their current one. Just giving code feels more like writing it for them and letting them claim the reward of releasing it, and that they'll be back a week later looking for more free handouts. Give a man a fish and all that. It is, however, just an opinion, so you are completely free to disagree with all of it, and write your own post about how to make a flying horse.