Home   Help Search Login Register  

Author Topic: Simple scripting  (Read 3029 times)

0 Members and 1 Guest are viewing this topic.

Offline Bontz07

  • Members
  • *
Simple scripting
« on: 16 May 2012, 18:36:40 »
Hey

Im trying to learn a bit of scripting and now I try to do very simple OFP cwc mission.

I have a question about script that makes a group move to the position that I want. Whit aid of internet I figured out something like this...

_group1 = _this select 0 (group that should move)
_P = _this select 1 (position where to move, an object on the map)

if trig5=true
   then
      {_group1 domove (getpos _P)}

That really doesn't work. What is the correct way to do this? Im a newbie 8).

How could I learn easily scripting? This is very interesting, but I don't find any good advice.

Is there any rule in which order the objects, arrays... etc comes? <-- How to know what is correct appearance of script?

« Last Edit: 16 May 2012, 18:46:12 by Bontz07 »

Offline Gruntage

  • Missions Depot
  • Administrator
  • *****
  • How do I get outta this chickensh*t outfit?
Re: Simple scripting
« Reply #1 on: 16 May 2012, 21:45:00 »
Welcome to the forums Bontz  :)

Basically the 'IF' command in OFP is in the format of:
Code: [Select]
if (a>b) then {goto "whatever"}
...or something like that.

Instead of what you put, try using this:

Code: [Select]
? trig5: leader _group1 domove (getpos _P)

It's been a few weeks since I lasted scripted anything so I can't remember whether there's any better way of doing what you wanted.

When I started learning sqs for the first time I just looked through BIS's missions and the numerous threads in this section of the forum.

As for your last question, there isn't really any specific order to go by. Just remember that when doing:

Code: [Select]

_bla = _this select <insert number>


...you start with '0'. Though I think you've already worked that out.

It's hard to give advice without listing too much information at once. You could try searching through the editor's depot for tutorials, dpbo'ing a few missions here and there. The COMREF here will furnish you with all the necessary info on the various commands.

Hope this helps
Gruntage

Additional: Just one piece of advice I will give is to make use of labels within a script to separate parts out. It's also much easier working with a script that isn't overcrowded or filled with needless stuff (like unused variables), so make sure you get rid of (or comment out, by putting ; before a command line) stuff you're no longer using in a script  :)
« Last Edit: 16 May 2012, 21:50:48 by Gruntage »
"But one thing I can tell you from not just OFP but life in general:  criticism is directly proportional to quality. The more criticism a mission receives, the better the outcome" - macguba

Offline h-

  • OFPEC Site
  • Administrator
  • *****
  • Formerly HateR_Kint
    • OFPEC
Re: Simple scripting
« Reply #2 on: 17 May 2012, 08:24:20 »
Quote
Is there any rule in which order the objects, arrays... etc comes?
If by objects you mean what they generally mean in "real" coding languages, sqs scripting has none.
The only objects we know is a entity/object in the game world that is passed into a script.

So if you have some OOP experience you kinda need to throw that out before learning sqs :P

There is this tutorial package avalaible at our Editors Depot, it is quite ancient (it is in html form after you unpack it) but it has a scripting tutorial part in it which would most likely get you started. Haven't checked but it might contain old links to our site which are no longer valid but otherwise it should be just fine.

The ComRef Gruntage linked you to is a excellent resource, just remember that it also contains scripting commands for Arma1 and 2 which obviously won't work in OFP.
Project MCAR   ---   Northern Fronts   ---   Emitter 3Ditor
INFORMATIVE THREAD TITLES PLEASE. "PLEASE HELP" IS NOT ONE..
Chuck Norris can divide by zero.

Offline faguss

  • Members
  • *
    • Faguss' Website
Re: Simple scripting
« Reply #3 on: 17 May 2012, 19:40:57 »
Quote
if trig5=true
   then
      {_group1 domove (getpos _P)}

  • SQS scripts are parsed line by line so you can't break one command into multiple lines
  • Condition should be in parentheses: if (condition) then {}
  • You've used assign operator '=' instead of equality '=='
  • Bool values cannot be compared to anything so you have to write: if (trig5)
« Last Edit: 17 May 2012, 19:44:59 by faguss »

Offline Bontz07

  • Members
  • *
Re: Simple scripting
« Reply #4 on: 27 Sep 2012, 19:41:00 »
Long time, no see.

Starting to work whit scripts again. I haven't had enough time to think these laterly, so...

What is the diffrence between if, then and ?, : commands? What does ? and : mean?

Also, what is the difference between using straightly name of a unit than using "select 0..." Does it have something to do whit local and global things? What is the diffrence between local and global? Things. What are they?

Also, how do you do scripts? Really. How do you use for example, if then commands to conditioning? Lets say, that I want heli to fly LZ, unload cargo and fly away. Of course I could do this easily whit waypoints, but how 'bout scripting? Could it be something like this...:

_grp = _this select 0
_heli = _this select 1
_pos1 = _this select 2
_pos2 = _this select 3

{_x moveincargo _heli} foreach units _grp

_heli domove (getpos _pos1)

if (!( ...
 
How could I continue that script? Is there any simple examples that I could apply for scripting? I haven't found any good yet. I need to advance in this thing.


Offline Gruntage

  • Missions Depot
  • Administrator
  • *****
  • How do I get outta this chickensh*t outfit?
Re: Simple scripting
« Reply #5 on: 27 Sep 2012, 20:19:09 »
There isn't much difference between if, then and ?,: commands. 'IF' is used in the format:

Code: [Select]
if (a > b) then {c = true}
But you could use 'else' as well:

Code: [Select]
if (a == b) then {goto "c"} else {exit}
? is used to start a condition, : is the 'On Activation'.

Local variables are confined to scripts. This means they cannot be used elsewhere. Global variables are used everywhere; in scripts, in the mission etc.

Global variables may make things simpler at times, but having too many global variables will cause multitudes of problems down the line. For example, OFP has a rather annoying bug called the 'savegame' bug, which is caused by having an overload of global variables, or scripts running at the same time.

Therefore, you'll want to use as many local variables as you can. It is possible to make a mission and confine everything you would normally want to make loads of scripts for, into one single script.

'IF' commands for conditioning are used similarly to '?' and ':'. It depends what you want your script to do. With the script you posted, you would probably want the script to wait until a certain condition is met right?

You wouldn't use '?' or 'IF' for that. You would use '@'. The '@' command is the same as 'waituntil'. Basically when this command is used, it freezes the script until a condition is met.

Example of usage:

Code: [Select]
@ !(alive (leader _grp))
player sidechat "The captain's dead!"

When the leader of _grp is killed, the script continues. I used a very basic example and it was the first thing that I thought of. Very handy command.

Hope this helps
"But one thing I can tell you from not just OFP but life in general:  criticism is directly proportional to quality. The more criticism a mission receives, the better the outcome" - macguba

Offline savedbygrace

  • Intel Depot
  • Administrator
  • *****
  • Be swift to hear...slow to speak...slow to wrath.
Re: Simple scripting
« Reply #6 on: 28 Sep 2012, 04:29:26 »
Great post(s) Gruntage. I would like to add that you should be careful with your naming conventions for global variables since every global variable can clash with other global variables used by addons and even the engine. That's why we encourage folks to create a tag and append their global variables with it to prevent catastrophes such as that.

If the unit is a primary piece to be accessed from scripts quite frequently, or has been assigned an identity, then assigning it's own global variable(name) is worth it. If you need to control groups or vehicles, using commands like driver, gunner, commander, leader, etc. are handy and eliminate needless global variables. If you want to access the player, the core game has assigned a global variable to that unit called "player".

Browse through the COMREF to get a feel for the commands. You won't regret the time spent. Make sure you select OFP so that you don't try and use commands from the later titles.

Offline Nikiller

  • Nogova Most Wanted
  • Members
  • *
  • ofp scripting addict
    • [LOL] ArmA ofp Site
Re: Simple scripting
« Reply #7 on: 28 Sep 2012, 10:33:51 »
hi,

Good thing with "if" is you can create more complexe conditions. You can have a condition in the condition.

Example:
Code: [Select]
#wait
~_delay1
? !(alive _z): goto _ende
if ([nik_z_target,_z,_aggroradius] call nik_z_finzone) then {if((dayTime>_sunrise) && (dayTime<_sunset)) then {_z setSkill _dayskill} else {_z setSkill _nightskill}; _z stop false} else {goto _wait}

It is just part of a script I am working on and it means nothing as it is but it shows how you can make complexe condition with "if".

@ command needs to be used wisely since it is basically a very fast loop who check a condition per frame. If you use too much @ you will end with poor performance. It's ok to use it in certain case with simple condition.

Use it ONLY if you need a very fast execution and if you have simple condition.

Example of @ usage:
Code: [Select]
_u = _this select 0
_g = _this select 1

_posg=getPos _g
_u doMove _posg
@unitReady _u || !(alive _u)
? (alive _u): _u sideChat "I'm in position."

exit

IMHO, for an alive check it is better to save performance by using a slow loop (>0.5sec)
Code: [Select]
_u=_this select 0

_l="l"
_d=1

#l
~_d
? (alive _u): goto _l

player sideChat "Ho no! He needs a bodybag..."

exit

For your chopper insertion here's a script (SP/MP compatible):

init.sqs
Code: [Select]
;********************************
;init Script by Nikiller v0.9b
;contact: nikillerofp@hotm{ail.fr
;[] exec "scriptName.sqs}"
;********************************

nik_host=local server

;-----------------------------------------------------------------------------------------
; Chopper insertion
;-----------------------------------------------------------------------------------------
[EastInsetionChopper1,gl_pad,gl_base] exec "chopper_insertion.sqs"

exit

chopper_insertion.sqs
Code: [Select]
;**********************************************************
;Chopper Insertion Script by Nikiller v0.9b
;Chopper unload cargo and return to base
;Note: Place a game logic named server on the map
;contact: nikillerofp@hotmail.fr
;[chopperName,destinationName,baseName] exec scriptName.sqs
;**********************************************************

if nik_host then {} else {goto "ende"}

_chop = _this select 0
_pad  = _this select 1
_base = _this select 2

_dr=driver _chop
_gu=gunner _chop
_cr=crew _chop
_cargo=_cr-[_dr,_gu]
_i=0
_j=count _cargo
_pp=getPos _pad
_pb=getPos _base
_chop setCaptive true
_chop setBehaviour "CARELESS"
_chop setCombatMode "BLUE"
{_dr disableAI _x} forEach ["TARGET","AUTOTARGET"]
{_gu disableAI _x} forEach ["TARGET","AUTOTARGET"]
_ac="GETOUT"

#movepad
_chop doMove _pp
~10
? _chop distance _pad>500 && canMove _chop: goto "movepad"
? !(canMove _chop): goto "ende"

;{unassignVehicle _x} forEach _cargo
_chop flyInHeight 1
_chop land "get out"

@ (getPos _chop select 2 < 1.5) || !(canMove _chop)
? !(canMove _chop): goto "ende"

_smokes="smokeShellRed" createVehicle (getPos _chop)

~1

#unload
(_cargo select _i) action [_ac,_chop]
unassignVehicle (_cargo select _i)
[(_cargo select _i)] orderGetIn false
_i=_i+1
~0.5
? _j>_i: goto "unload"

~5
_chop flyInHeight 100

#movebase
_chop doMove _pb
~10
? _chop distance _base>500 && canMove _chop: goto "movebase"

~10
_all=[_chop,_dr,_gu]
~5
{deleteVehicle _x} forEach _all

#ende

exit

The code could be optimized but it should work well as is it.

Here's a demo to show how it works: DEMO LINK

cya.

Nikiller.
« Last Edit: 28 Sep 2012, 12:15:14 by Nikiller »

Offline Bontz07

  • Members
  • *
Re: Simple scripting
« Reply #8 on: 28 Sep 2012, 12:56:52 »
Thanks for your posts, they were all very useful! Thanks!

I read trough Nikiller sent code, which I understood pretty well. But I wonder that _i=0 variable. It is used by "select _i". Does it have any diffrence to select 0? I find it to be same thing. Right?

Also, using if/then, ?/: and @ makes script wait until condition of that part is true, right?

This time no more questions. B)


Offline Gruntage

  • Missions Depot
  • Administrator
  • *****
  • How do I get outta this chickensh*t outfit?
Re: Simple scripting
« Reply #9 on: 28 Sep 2012, 14:08:09 »
Correct. When you say, for example:

Code: [Select]
_g = units (leader (_eGroups select _i))
The local variable _i must be defined before this command is used. _i can be used to represent anything, but in this case, it needs to represent 0.

So, when the script starts, I put:

Code: [Select]
_i = 0
So, the _i variable is defined.

When you're using if/then and ?/:, what you must remember is that if the condition is not met by the time the script reaches that point, it won't wait until the condition is met. Example:

Code: [Select]
? not (alive captain): player sidechat "We need a medic over here!"

In this example, if when the script gets to that condition, and the captain is not dead, the script won't just stop until the condition is made true.

Unless, you use a loop, or the @ command.

But, for simple conditions like checking when a loon is dead, or when a vehicle is destroyed, you could just use a trigger in-game.

I try to avoid using many looping scripts if I can help it. I'll also destroy triggers after their condition has been met (unless they're set to repeatedly). Triggers that have been....triggered, are no longer of any use unless they have been set to repeat.

Anyway, I digress.

Hope that answers your questions
"But one thing I can tell you from not just OFP but life in general:  criticism is directly proportional to quality. The more criticism a mission receives, the better the outcome" - macguba

Offline Bontz07

  • Members
  • *
Re: Simple scripting
« Reply #10 on: 28 Sep 2012, 17:57:27 »
Hey.

Few questions again. B) This time i'd like to ask about groups.

First of, how do insert a group into a script? I cant get it working whit like "_grp = units _this select 0". How do you identify a group so that script can be read.

Also, is it possible to make waypoints via script? Mostly I want to know can you use domove/move commands to move whole group and even so that the leader would use radio to informate "where to go".

Currently I can make only leader to move place to other, but I cant make whole group to move whit him.

And last, as we know, group leader orders his team. How can you script leader to order others to do something? For example to get in to a car. I tried to do this whit action command, but these men "teleports" next to it. Of course you could also do this whit waypoints, but to be honest, I don't like to use them.

Im not sure how annoying these my questions are, but I hope you answer these. :S

Offline Gruntage

  • Missions Depot
  • Administrator
  • *****
  • How do I get outta this chickensh*t outfit?
Re: Simple scripting
« Reply #11 on: 28 Sep 2012, 18:18:46 »
Well, you can name groups in the editor:

Code: [Select]
egroup1 = group this
Put that in the init of the leader of a group.

In a script, you can use:

Code: [Select]
_egrp = units egroup1
_egrp is now a local variable consisting of all of the units in egroup1

You can also do this:

Code: [Select]
_grp = _this select 0

_egrp = units _grp

Here, local variable _grp is defined elsewhere. Script would be called:

Code: [Select]
[egroup1] exec "script.sqs"

As for your other questions, I think 'commandMove' will make a group leader order his troups to a location.

In order for a group leader to order a unit to board a vehicle, try this:

Code: [Select]
_unit assignasgunner _gun

_unit orderGetIn true

_unit is the unit you want to be ordered into a vehicle. _gun is the vehicle. This example orders a loon to man a machinegun (or any other vehicle with a gunner position). Other 'assignas' commands include:

assignasdriver
assignascommander
assignascargo (not sure about this one)

Hope this helps

Questions such as these are far from being annoying. We all started out with limited knowledge of OFP editing. Answering questions like these was actually how OFPEC became what it is today. So, by all means ask as many questions as you like and we will try to answer them  :)
« Last Edit: 28 Sep 2012, 18:22:00 by Gruntage »
"But one thing I can tell you from not just OFP but life in general:  criticism is directly proportional to quality. The more criticism a mission receives, the better the outcome" - macguba

Offline Bontz07

  • Members
  • *
Re: Simple scripting
« Reply #12 on: 28 Sep 2012, 18:46:35 »
Yep, thats it. Thank you Gruntage! You are making this much easier.  :good:

Edit*

Scriptings going good, and starting to understand something. B)

Now I have simple question to ask.

Could it be possible to make a "radius position"? This concerns about moving units. When I put " _Mr move getpos _Guy ", this Mr. moves right to the position where Guy is standing. So I want they to have some space between them. More realistic.

Edit*

Another question. How can I make, after beeing detect by enemy, so that they send a patrol to a last know position of my group? Also, how do you spawn units? B)

« Last Edit: 02 Oct 2012, 13:55:25 by Bontz07 »

Offline Bontz07

  • Members
  • *
Re: Simple scripting
« Reply #13 on: 02 Oct 2012, 14:06:41 »
God dag!

Trying to make simple patrol/guard script. It works somehow, but I cant get working "waituntill" command and "random" command in correct way. The code looks like this:

Code: [Select]
_center = _this select 0
_patrol = _this select 1


#move

_rdm = random 100
_wait = random 30

_pos = [(getpos _center select 0) +_rdm, (getpos _center select 1) +_rdm]

_patrol move _pos

@ _patrol distance _pos < 10

~_wait

_pos = objNull
_rdm = objnull
_wait = objNull

~0.2

goto "move"

Why cannot the script understand @ _patrol distance _pos < 10 part? Also, could it be possible to get negative numbers as random or any other way to get patrol move on the negative side of the center?

Im starting to proceed in scripting. Slowly but very confidently.  :whistle:

Offline Gruntage

  • Missions Depot
  • Administrator
  • *****
  • How do I get outta this chickensh*t outfit?
Re: Simple scripting
« Reply #14 on: 02 Oct 2012, 15:08:19 »
Quote
Could it be possible to make a "radius position"? This concerns about moving units. When I put " _Mr move getpos _Guy ", this Mr. moves right to the position where Guy is standing. So I want they to have some space between them. More realistic.

^ Fairly sure I can answer this one. It's more complex than just telling a unit to move some distance from another unit:

Code: [Select]
#LOOP
? (_unit1 distance _unit2) < 5.5: _unit1 switchMove "CivilRunF"; goto "next"

goto "loop"

#NEXT
_pos = getpos _unit1

_unit1 setdir ((getpos _unit2 select 0) - (_pos select 0)+.001) atan2 ((getpos _unit2 select 1)

~0.5
goto "LOOP"

That should move a unit 5m from another unit.

Quote
Another question. How can I make, after beeing detect by enemy, so that they send a patrol to a last know position of my group? Also, how do you spawn units? B)

There are several ways to answer your first question. One method that springs to mind would be to setpos a gamelogic to the position of the player, and move an enemy squad to that location. BUT, you would want to do something like this:

Code: [Select]
[groupOne, 1] setWPPos [(getpos _logic select 0)+ 500,(getpos _logic select 1)+ 500,0]

This will move a group's waypoint some distance away from the gamelogic's location. This is preferable to sending the group to the exact location of the player, because that would be cheating. This method will keep the player on his toes, but it won't make him feel that he's trapped.

To spawn a unit, use this:

Code: [Select]
"soldierE" createUnit [getMarkerPos "SpawnMarker",campgunner,"", 1, "corporal"]

createunit is in the format of:

[pos (Position), group (Group),init (String), skill (Number), rank (String)]

See the COMREF for more details.

To my knowledge, it's not possible to get negative random numbers.

As for the @ command, you could try this:

Code: [Select]
#LOOP
? (_unit1 distance _unit2) < 5.5:  goto "next"

goto "loop"

Like the example I gave to answer your first question.

I would suggest making a thread for each question, or better yet, make use of the search function.

Hope this helps


"But one thing I can tell you from not just OFP but life in general:  criticism is directly proportional to quality. The more criticism a mission receives, the better the outcome" - macguba