Author Topic: scripting.html  (Read 8505 times)

0 Members and 1 Guest are viewing this topic.


 
 :nervous: Oops
« Last Edit: July 06, 2012, 10:25:47 am by The_Force »
May the Force be with you

 

Offline Aginor

  • Spelljammer
  • 210
No, I added it directly to the file.
but... ...actually I think I should check my PC later, maybe the file is there and I just didn't see it, or the exe wasn't able to save the file because of some strange WinXP Professional 64 (I still curse the day I bought that one) rights issue or something.
Member of the Scooby Doo model Fanclub "verticies and splines are the medium and he is the artist."

 
It's in the directory before the file you modify.
May the Force be with you

 

Offline Aginor

  • Spelljammer
  • 210
Oh man.... turns out it was there all the time, I just never looked in that folder. I somehow assumed it would be in the same folder as the exe, which it of course isn't.
Sorry for stirring everyone up!
<-- feels really stupid now


But while I'm here I got a question:
Is there a possibility to trigger a script even whenever a certain event in the mission becomes true? Maybe by monitoring a SEXP variable?

My problem is the following:
My player cloaking events are working and all, but since I change the player ship's model to another one to have animated cloaking the secondaries reset to the standard missile type and the maximum number.
Until now I just limited the player to that one missile type and stored the number of missiles in a variable. As soon as the event has changed the model it sets the secondary ammo to the stored value.
But since there is no SEXP to set the type of secondary (I think there is one in other builds but not here it seems) I thought I could maybe do it by scripting.

Here's what I tried so far:

Code: [Select]

      -- Mission starts and player flies the Strakha, I read the type of secondary weapon from bank 1 (there is only one)
      -- edited it, first version was even worse, didn't work as intended.

misTime = mn.getMissionTime()
if (misTime == 1 and playerShip.Class.Name == "Strakha" and Weapinit == 0) then
orgWeapClass = playerShip.SecondaryBanks[1].WeaponClass.Name
Weapinit = 1
end




      -- When the player is cloaking or cloaked  OR has just finished decloaking,
      -- set the secondary type to the one he is supposed to have

       if (
(     playerShip.Class.Name == "Strakha#Inv"
   or playerShip.Class.Name == "Strakha#Cloak"
   or playerShip.Class.Name == "Strakha#Decloak"
)
or
(
      playerShip.Class.Name == "Strakha"
  and Weapinit == 1
)
) then

playerShip.SecondaryBanks[1].WeaponClass = tb.WeaponClasses[orgWeapClass]
end


I know that code is far from perfect. But worse is: I do that "On Frame" at the moment, which sucks of course. I want to only do that when the player just triggered the cloaking.
Also there is the problem that if the player carries missiles that are smaller than the standard WCS missiles (those are all of the same size) the number is set to the maximum number of standard missiles the ship can carry. That's because when changing the ship model the number of missiles is set to the default number for a short moment before the script changes the type.

Any ideas?


EDIT: Ok, found another error.
« Last Edit: July 06, 2012, 02:55:18 pm by Aginor »
Member of the Scooby Doo model Fanclub "verticies and splines are the medium and he is the artist."

 
Quote
Is there a possibility to trigger a script even whenever a certain event in the mission becomes true? Maybe by monitoring a SEXP variable?

Create a function in LUA after
$On Mission Start:
or
$On Gameplay Start:
or whatever you want
Code: [Select]
$Application: FS2_Open
$On Mission Start:
[
function = changestuff(x)
if x=1 then
<do stuff>
...

and call that function in fred with the script-eval sexp like script-eval "changestuff(1)"

You can do it via a changing sexp-variable in Fred but that one would still require $On Frame so I think a function call out of Fred is way better.

« Last Edit: July 06, 2012, 02:58:00 pm by Admiral MS »
Here goes scripting and copy paste coding
Freespace RTS Mod
Checkpoint/Shipsaveload script

 

Offline Aginor

  • Spelljammer
  • 210
Ah thanks!

Maybe I can even change some more things in the script so I have to do less in the events. That way mission designers that want to use the Strakha don't have to include six events that have a horrible number of SEXPs in them.
Member of the Scooby Doo model Fanclub "verticies and splines are the medium and he is the artist."

 
Everything you can change by using Fred events can be done within the scripting system as well. It allows you to call every possible SEXP.

And for your missile number problem:

Code: [Select]
playership.Class = tb.ShipClasses["name"]
playership.SecondaryBanks[x].WeaponClass = tb.WeaponClasses["name"]
playership.SecondaryBanks[x].AmmoLeft = number
in this order

and if it still fails you can add:
Code: [Select]
playership.SecondaryBanks[x].AmmoMax = number2
before AmmoLeft to overwrite the table setting.

If this doesn't work... in the BtA Demo and my test missions it definetly works.
Here goes scripting and copy paste coding
Freespace RTS Mod
Checkpoint/Shipsaveload script

 

Offline Aginor

  • Spelljammer
  • 210
The problem is that I have to determine the number of missiles just before switching the models, but at the moment my script runs when the ship class has already changed (so there is already the wrong number of missiles - the maximum number - in the bank)

But maybe I have the solution for that already. I'll try that. And if it works I think I will put all the stuff into the script instead of the events. Let's see....
Member of the Scooby Doo model Fanclub "verticies and splines are the medium and he is the artist."

 
Change the shipclass within the script instead of FRED and save AmmoLeft before doing that would be the obvious solution.

Code: [Select]
number = playership.SecondaryBanks[x].AmmoLeft
number2 = playership.SecondaryBanks[x].AmmoMax

playership.Class = tb.ShipClasses["name"]
playership.SecondaryBanks[x].WeaponClass = tb.WeaponClasses["name"]
playership.SecondaryBanks[x].AmmoMax = number2
playership.SecondaryBanks[x].AmmoLeft = number

And if you need a delay between the events do it in 2 different functions sharing the variables or with a delay function in LUA.
Here goes scripting and copy paste coding
Freespace RTS Mod
Checkpoint/Shipsaveload script

 

Offline Aginor

  • Spelljammer
  • 210
Yeah, I guess I'll do that.
But first I'll have to fix my script. I somehow destroyed it during one of my last changes :D
Member of the Scooby Doo model Fanclub "verticies and splines are the medium and he is the artist."

 

Offline Aginor

  • Spelljammer
  • 210
Ok, most stuff is working now. I had a bit of trouble running SEXPs but the forum search helped me. I never would have guesses it is the "!". The exclamation mark is hardcoded in my brain as a negation already because it is the same in almost every programming language. And of course it isn't the negation in LUA as I had to learn.... :D

Anyway, here's my next question: Admiral MS, you were talking about a LUA delay function or something.
I searched for "delay", "sleep", and "wait" (those are the most common names for such a function in script languages) in the LUA documentation but couldn't find it yet. Can anyone point me to an example?

For those interested in my cloaking script here it is how it looks now:

in the mission there are four events that trigger the "p_CloakOrder" function and keep track of the cloaking status. The player can't cloak or decloak more often than every 5 seconds (because the cloaking and decloaking animations take three seconds), that is done by the events at the moment. The whole other stuff is done by the script below.

I'm using a ghost named cloak_ghost in the mission to store the player's damage. Is there a more elegant way?

Code: [Select]
-- ------------------------ Cloaking -----------------------------


p_CloakOrder = function(par_order)
playerShip = hv.Player

if (par_order == 1) then
p_Cloaking(0)
end

if (par_order == 2) then
p_Cloaked(0)
end

if (par_order == 3) then
p_Decloaking(0)
end

if (par_order == 0) then
p_Decloaked(0)
end

return 0
end


p_Cloaking = function(x)
mn.runSEXP("play-sound-from-table !0 !0 !0 !144")
orgWeapClass = playerShip.SecondaryBanks[1].WeaponClass.Name
orgAmmo = playerShip.SecondaryBanks[1].AmmoLeft
orgEnergy = playerShip.WeaponEnergyLeft
mn.runSEXP("ship-copy-damage !" .. tostring(playerShip.Name) .. "! !cloak_ghost!")
mn.runSEXP("change-ship-class !Strakha#Cloak! !".. tostring(playerShip.Name) .. "!")
mn.runSEXP("ship-copy-damage !cloak_ghost! !" .. tostring(playerShip.Name) .. "!")
playerShip.SecondaryBanks[1].WeaponClass = tb.WeaponClasses[orgWeapClass]
playerShip.SecondaryBanks[1].AmmoLeft = orgAmmo
playerShip.WeaponEnergyLeft = orgEnergy
mn.runSEXP("lock-primary-weapon !" .. tostring(playerShip.Name) .. "!")
mn.runSEXP("lock-secondary-weapon !" .. tostring(playerShip.Name) .. "!")
mn.runSEXP("hud-set-text !Cinfo! !    Cloaking!")
return 0
end


p_Cloaked = function(x)
orgWeapClass = playerShip.SecondaryBanks[1].WeaponClass.Name
orgAmmo = playerShip.SecondaryBanks[1].AmmoLeft
orgEnergy = playerShip.WeaponEnergyLeft
mn.runSEXP("ship-copy-damage !" .. tostring(playerShip.Name) .. "! !cloak_ghost!")
mn.runSEXP("change-ship-class !Strakha#Inv! !".. tostring(playerShip.Name) .. "!")
mn.runSEXP("ship-copy-damage !cloak_ghost! !" .. tostring(playerShip.Name) .. "!")
playerShip.SecondaryBanks[1].WeaponClass = tb.WeaponClasses[orgWeapClass]
playerShip.SecondaryBanks[1].AmmoLeft = orgAmmo
playerShip.WeaponEnergyLeft = orgEnergy
mn.runSEXP("protect-ship !" .. tostring(playerShip.Name) .. "!")
mn.runSEXP("hud-set-text !Cinfo! !    Cloaked!")
return 0
end


p_Decloaking = function(x)
mn.runSEXP("play-sound-from-table !0 !0 !0 !145")
orgWeapClass = playerShip.SecondaryBanks[1].WeaponClass.Name
orgAmmo = playerShip.SecondaryBanks[1].AmmoLeft
orgEnergy = playerShip.WeaponEnergyLeft
mn.runSEXP("ship-copy-damage !" .. tostring(playerShip.Name) .. "! !cloak_ghost!")
mn.runSEXP("change-ship-class !Strakha#Decloak! !".. tostring(playerShip.Name) .. "!")
mn.runSEXP("ship-copy-damage !cloak_ghost! !" .. tostring(playerShip.Name) .. "!")
playerShip.SecondaryBanks[1].WeaponClass = tb.WeaponClasses[orgWeapClass]
playerShip.SecondaryBanks[1].AmmoLeft = orgAmmo
playerShip.WeaponEnergyLeft = orgEnergy
mn.runSEXP("hud-set-text !Cinfo! !   Decloaking!")
return 0
end


p_Decloaked = function(x)
orgWeapClass = playerShip.SecondaryBanks[1].WeaponClass.Name
orgAmmo = playerShip.SecondaryBanks[1].AmmoLeft
orgEnergy = playerShip.WeaponEnergyLeft
mn.runSEXP("ship-copy-damage !" .. tostring(playerShip.Name) .. "! !cloak_ghost!")
mn.runSEXP("change-ship-class !Strakha! !".. tostring(playerShip.Name) .. "!")
mn.runSEXP("ship-copy-damage !cloak_ghost! !" .. tostring(playerShip.Name) .. "!")
playerShip.SecondaryBanks[1].WeaponClass = tb.WeaponClasses[orgWeapClass]
playerShip.SecondaryBanks[1].AmmoLeft = orgAmmo
playerShip.WeaponEnergyLeft = orgEnergy
mn.runSEXP("unlock-primary-weapon !" .. tostring(playerShip.Name) .. "!")
mn.runSEXP("unlock-secondary-weapon !" .. tostring(playerShip.Name) .. "!")
mn.runSEXP("unprotect-ship !" .. tostring(playerShip.Name) .. "!")
mn.runSEXP("hud-set-text !Cinfo! !    Visible!")
return 0
end
-- ---------------------------------------------------------------
Member of the Scooby Doo model Fanclub "verticies and splines are the medium and he is the artist."

 

Offline m!m

  • 211
You can access and change the hitpoints of the player object using the HitpointsLeft field.

I'm not aware of any functions in LUA (which could be used in the way FSO handles lua scripts) that would work like the sleep functions in other languages.

 
Anyway, here's my next question: Admiral MS, you were talking about a LUA delay function or something.
I searched for "delay", "sleep", and "wait" (those are the most common names for such a function in script languages) in the LUA documentation but couldn't find it yet. Can anyone point me to an example?
I'm not aware of any functions in LUA (which could be used in the way FSO handles lua scripts) that would work like the sleep functions in other languages.
Right - there is no integrated LUA function (as far as I know it would cause the interpreter stop doing things and freeze FSO). So no easy way to delay something.

What I called a "delay function" is a workaround several scripts use. It's a function that checks how much time has passed and activates when time passed is larger than the specified delay.
Code: [Select]
$Application: FS2_Open
$On Gameplay Start: [
ammodelay = {}
delay = 1

bla = function()
...
AmmoLeft = ...
ammodelay.AmmoLeft = AmmoLeft
ammodelay.starttime = mn.getMissionTime()
end
]

$On Frame:[
if (mn.getMissionTime() - ammodelay.starttime) > delay then
    playerShip.SecondaryBanks[1].AmmoLeft = ammodelay.AmmoLeft
end
]
You can use such a delay so set some boolean variables after 5 seconds that enable or disable the cloaking functions.

Quote
I'm using a ghost named cloak_ghost in the mission to store the player's damage. Is there a more elegant way?
If you want to copy damage only it's m!m's solution with HitpointsLeft and possibly a loop through the subsystems to get their hitpoints as well. In case you want everything out of shipdata down to Shields, Energy and whatever you can get these values as well and store them - the functions might get a bit longer and complicated though.
« Last Edit: July 07, 2012, 10:47:32 am by Admiral MS »
Here goes scripting and copy paste coding
Freespace RTS Mod
Checkpoint/Shipsaveload script

 

Offline Aginor

  • Spelljammer
  • 210
Quote
What I called a "delay function" is a workaround several scripts use. It's a function that checks how much time has passed and activates when time passed is larger than the specified delay.

Ah, ok. It is basically a state machine.
I did it similarly and now I need only two events for player cloaking.


Quote
want everything out of shipdata down to Shields, Energy and whatever you can get these values as well and store them - the functions might get a bit longer and complicated though.

I'm doing that at the moment.

Btw: Is there any possibility to get and set the energy management bars? Those are one of the things that reset when changing models. Most of the rest is already in my script now.
Member of the Scooby Doo model Fanclub "verticies and splines are the medium and he is the artist."

 

Offline Nuke

  • Ka-Boom!
  • 212
  • Mutants Worship Me
for delays just use timestamps. some pseudocode:

timestamp = current time + how long you want it to last

if timestamp is more than current time
 do stuff
 --if we want to do this again at some interval
 timestamp = current time + how long you want it to last
end

the timestamp will be handled on the next frame that the if returns true. note that this may result in some lost time, because it will be very unlikely the code will be evaluated exactly when the timestamp expires. so if you need to do something at a regular interval, you need to subtract the current time from the timestamp right after the timestamp expires to get the overtime, then subtract this from the next timestamp.
 
« Last Edit: July 07, 2012, 07:35:41 pm by Nuke »
I can no longer sit back and allow communist infiltration, communist indoctrination, communist subversion, and the international communist conspiracy to sap and impurify all of our precious bodily fluids.

Nuke's Scripting SVN

 

Offline Aginor

  • Spelljammer
  • 210

Hi guys!

I have another two questions:
Is there a difference between evaluateSEXP() and runSEXP() ? It is not documented but I _think_ the return values are different. Any information about that?

The other thing is this:
I want to check whether the ship in the variable "nship" has been destroyed or not and act accordingly. So I wrote
Code: [Select]
destr = mn.evaluateSEXP("is-destroyed-delay !0! !".. tostring(nship.Name) .. "!")

if (not destr) then
-- stuff --
end
But I get only an error: "can't find operator in operator list"

What am I doing wrong?
Member of the Scooby Doo model Fanclub "verticies and splines are the medium and he is the artist."

 
As far as I know runSEXP() just returns whether it was able to do what it should or not.
evaluateSEXP() returns the result of the check like the name indicates  but has a slightly different syntax than runSEXP() for some reason:
Code: [Select]
result = mn.evaluateSEXP("(is-destroyed-delay !0! !"..shipname.."!)")
These functions are a good example of really bad/nonexisting documentation...
Here goes scripting and copy paste coding
Freespace RTS Mod
Checkpoint/Shipsaveload script

 

Offline Aginor

  • Spelljammer
  • 210
AH! Thanks a lot, I'll try that once I'm home.
Maybe we should really take a scripting.html from a recent build and comment all the functions, including examples, like you just did, plus common errors or things that look like they were possible with a function but aren't.

Because at the moment a scripting newbie doesn't have it easy. And I am a software developer, I can't even imagine how someone who has no programming/scripting experience yet could do scripts in FS2 based on what documentation we have.

The most useful stuff is in the wiki tutorials and (even more useful) the scripting examples, but the tutorials are very basic and you quickly reach the point where you just don't know how to actually use the functions the scripting.html tells you about. I figured most of it out after a while, but there are many people who don't even understand the error texts or the syntax description. (ok, they could be worse. At least they are not BNF :D )
Member of the Scooby Doo model Fanclub "verticies and splines are the medium and he is the artist."

 

Offline Nuke

  • Ka-Boom!
  • 212
  • Mutants Worship Me
you can edit the function descriptions in lua.cpp so that the game generates more useful instructions automatically. not sure if there is any string length limits there. you might be able to include a couple paragraphs of commentary on a thing and do a way with one liner documentation which seems to plague scripting.html (and much of the wiki). details are important. i tend to fix up any bad documentation every time i screw around in that piece of code. but i make sure i understand how something works before i start spewing out potentially wrong information. events <-> scripting interfaces are kind of a grey area for me since i really never learned how the events system works. think after over a decade of freespace modding this would have been a skill id have picked up by now. :D
I can no longer sit back and allow communist infiltration, communist indoctrination, communist subversion, and the international communist conspiracy to sap and impurify all of our precious bodily fluids.

Nuke's Scripting SVN