Quantcast

Jump to content

» «
Photo

Mission Coding for Pro's!

1 reply to this topic
Dutchy3010
  • Dutchy3010

    Female SCM coder!

  • Moderator
  • Joined: 30 Jul 2006
  • Netherlands
  • Best Script 2013 [DYOM]
    Best Script 2012 [DYOM]

#1

Posted 03 May 2009 - 06:15 PM Edited by Dutchy3010, 03 May 2009 - 06:18 PM.

Mission Coding for Pro's!

By PatrickW and Dutchy3010


This topic is a continuation of the Mission Coding for Dummies tutorial. We will explain the more advanced parts of SCM Coding. In this tutorial, you won't find how to create actors, or how to make a text ingame. In this tutorial, you will find advanced things, like how to write readable code and how to use the SCMLOG Cleo extension. So if you can't make an easy mission, or haven't coded at all, then you should start with the other topic (Mission coding for dummies). This topic is, just like the Mission Coding for Dummies tutorial, in continual update. SCM Coding is very wide, you can do all sort of things with it. That's why we are able to make many tutorials about it.

For this tutorials you need:
  • SannyBuilder (Download)
  • Grand Theft Auto: San Andreas
  • Experience in SCM Coding
Content: Links: The reactiontopic is the same as the one for Mission Coding for Dummies. You can ask questions about the content of this tutorial, but you can also suggest new subjects for tutorials.

PatrickW
  • PatrickW

    GTA Juggernaut

  • Inactive Staff
  • Joined: 07 Jan 2004
  • Netherlands
  • Best Script 2013 [DYOM]
    Best Script 2012 [DYOM]

#2

Posted 03 May 2009 - 06:17 PM Edited by PatrickW, 03 May 2009 - 06:20 PM.

The commandments of readable code.
The SCM en CLEO coding style-guide


user posted image

This guide asumes that you already know the concepts of SCM en CLEO programming and that you are able to write code that is understood by the compiler and that does what you want it to do. This guide presents you with a suloution to an additional challenge: Write code that people can understand.
How often have you looked at a piece of code that you wrote some time ago, and have difficulty to understand it again. How often have you tried to answer a question about a piece of code on the forums, but you have great difficulty to comprehend what the code is suppose to do in the first place.

The Commandments of SCM Coding
  • Thou shalt use Sannybuilder for thy SCM coding.
  • Thou shalt use high-level constructs wherever possible.
  • Thou shalt use object notation when available.
  • Thou shalt not code without proper identation.
  • Thou shalt comment thy code.
  • Thou shalt minimize thy labels.
  • Thou shalt declare thy variables.
  • Thou shalt name thy locals.
  • Thou shalt symbolize thy constants.
  • Thou shalt not give thy identifyers meaningless names.
  • Thou shalt describe the parameters of thy routines.



Thou shalt use Sannybuilder for thy SCM coding.
Although there are more tools available and everybody has their own reasons for using one or the other. But for readibility, sannybuilder offers the most support and many of the following commandments depend on these features.

Thou shalt use high-level constructs wherever possible.
The advantage of using these constructs is, that they immediatly reveal the structure of the code. Especially in combination with the next commandment, proper identation, this will reveal the overall structure of a piece of code at first glance.

Thou shalt use object notation when available.
The object notation that Sannybuilder provides, has a much more readable syntax than regular opcodes. Thus these should always be used where they are available as an alternative for normal opcodes.

Thou shalt not code without proper identation.
When code is properly idented, the structure becomes apparent immediatly. This is especially the case when using nested constructs, the identation will reveal where one constructs end, and where the other starts.

Thou shalt comment thy code.
Adding comments to your code offers you the option to state what each section of code is suppose to do, and how it contributes to the fuctionality ythat is implemented.

Thou shalt minimize thy labels.
Almost a direct result of the usage of high-level constructs, is the lack of need for using labels. Labels are especially cumbersome if you want to reuse a piece of code at another location in your file. Labels will conflict, and will have to be adapted. This also goes for all the references to the label, which might lead to some hard to find bugs if one is forgotten.

Thou shalt declare thy variables.
Using the VAR-END construct to declare the type of your variables has the advantage that it will enable you to use arithmetic and comparison commands without the need to prefix them with the numerical opcode. This will not onloy speed-up the coding, but will also make the code much more readable. Another advantage is that it gives you a central location where you van use comments to describe the meaning and usage of each variable.

Thou shalt name thy locals.
The usage of local variables has advantages in many cases, such as not taking up global memory space and is even mandatory for CLEO scripts. But the disadvantage is that using their numerical notation will deteriate the readibility, as the name bears no meaning. Therefor you should use the CONST-END construct to assign names to your locals, which will greatly improve the understandability of your code.

Thou shalt symbolize thy constants.
if you're using numerical or string constants in your code, it is adviseable to define them in a CONST-END construct, so that you can use the symbolic name in all places wehere the constant is used. This will not only better explain the mening of a specific constant value, but it is also very handy when after a while it turns out that a constant wasn;t that constant after all, and needs to be adapted. Now you can simply adapt the value at one position.

Thou shalt not give thy identifiers meaningless names.
A key method to improve the readibility of your code is to use meaningful names for all your identifiers: variables, constants and labels. The names of variables and constant should describe what they represent. If a label cannot be prevented, at least give it a name that accurately describes the functiuonality of the piece of code that follows.

Thou shalt describe the parameters of thy routines.
When defining Subroutines, not only add a comment that described the functionality, but also add comments with an exhaustive list of all variables that are used by the routine (input variables) and all variables that are adapted by the routine (output variables).



Example
First we will show you an example of a code which is violating every commandment. After that, we will fix the code.

CODE
{$CLEO}
:00
03A4: name_thread "MODEL"
0247: load_model #BFYST
0247: load_model #rocketla
0247: load_model #desert_eagle
0247: load_model #m4
038B: load_requested_models
0002: jump @01
:01
0001: wait 0 ms
00D6: if or
8248: not model #BFYST available
8248: not model #rocketla available
8248: not model #desert_eagle available
8248: not model #m4 available
004D: jump_if_false @101
0001: wait 0 ms
0002: jump @01
:101
0001: wait 0 ms
00D6: if
8256: not  player $PLAYER_CHAR defined
004D: jump_if_false @010
0001: wait 200 ms
0002: jump @101
:010
0001: wait 0 ms
009A: 10@ = create_actor_pedtype 5 model #BFYST at 2488.5601 -1680.84 13.3438
02E2: set_actor 10@ weapon_accuracy_to 90
0223: set_actor 10@ health_to 2000
01B2: give_actor $PLAYER_ACTOR weapon 24 ammo 30000
01B2: give_actor 10@ weapon 31 ammo 30000
0350: toggle_actor 10@ maintain_position_when_attacked 1
05E2: AS_actor 10@ kill_actor $PLAYER_ACTOR
01B2: give_actor $PLAYER_ACTOR weapon 35 ammo 10
01B9: set_actor $PLAYER_ACTOR armed_weapon_to 24
01B9: set_actor 10@ armed_weapon_to 31
0002: jump @10
:10
0001: wait 200 ms
00D6: if
0118: actor 10@ dead
004D: jump_if_false @10
0002: jump @100
:100
0394: play_music 1
01E3: show_text_1number_styled GXT 'M_PASS' number 10000 time 5000 style 1
0109: player $PLAYER_CHAR money += 25000
0249: release_model #BFYST
0249: release_model #rocketla
0249: release_model #desert_eagle
0249: release_model #m4
0A93: end_custom_thread


Fixed code:

CODE
{$CLEO}
{
 DEMO-SCRIPT
 by PatrickW and Dutchy3010
 (c) 2009
 
 This CLEO script executes as soon as a new game is started or a savefile is loaded.
 It spawns a woman with an M4 at Groove-street, who is determined to kill your player.
 To defend himself, tha player will receive a rocketlauncher and a desert_eagle.
 Killing the woman will be rewarded with $25000.
 
 Note: This Script was created for the SCM and CLEO Coding Style Guide.
 
 Feedback, please at <<< Topic URL >>>
}

:MODEL
thread "MODEL"

Const
 // Mapping of local Variables
 ATTACKER=10@
 
 // Id's used for weapon handling
 M4_ID=31
 ROCKETLA_ID=35
 DESERT_EAGLE_ID=24
End

Var
 ATTACKER : Actor  // The Actor that needs to be killed to pass this mission
End

{
Load the required models.
=================================================}
model.Load(#BFYST)
model.Load(#rocketla)
model.Load(#desert_eagle)
model.Load(#m4)

{                                                      
Wait for the models to be available.
=================================================}
While True
 wait 0 ms
 if and
   model.Available(#BFYST)
   model.Available(#rocketla)
   model.Available(#desert_eagle)
   model.Available(#m4)
 jf Break
end

{
Create Attacker, set properties and give her a M4.
=================================================}
ATTACKER = Actor.Create(CIVFEMALE, #BFYST, 2488.5601, -1680.84, 13.3438 )
Actor.WeaponAccuracy(ATTACKER)= 90
Actor.Health(ATTACKER) = 2000
0350: toggle_actor ATTACKER maintain_position_when_attacked 1
01B2: give_actor ATTACKER weapon M4_ID ammo 30000
01B9: set_actor ATTACKER armed_weapon_to M4_ID

{
Wait for the player to be available.
=================================================}
repeat
 wait $DEFAULT_WAIT_TIME ms
until Player.Defined($PLAYER_CHAR)  

{
Give the player a desert-eagle and a rocketlauncher,
and make the desert-eagle the active weapon.
================================================}
01B2: give_actor $PLAYER_ACTOR weapon ROCKETLA_ID ammo 10
01B2: give_actor $PLAYER_ACTOR weapon DESERT_EAGLE_ID ammo 30000
01B9: set_actor $PLAYER_ACTOR armed_weapon_to DESERT_EAGLE_ID

{
Now order the attacker to attack the player
and wait until the victim is killed.
================================================}
05E2: AS_actor ATTACKER kill_actor $PLAYER_ACTOR
repeat
 wait $DEFAULT_WAIT_TIME ms
until Actor.dead(ATTACKER)  

{
The Attacker is killed. The Mission is passed.
================================================}
0394: play_music 1
01E3: show_text_1number_styled GXT 'M_PASS' number 10000 time 5000 style 1  // MISSION PASSED!~n~~w~$~1~
Player.Money($PLAYER_CHAR) += 25000

{
Unload the loaded Models.
================================================}
model.Destroy(#BFYST)
model.Destroy(#rocketla)
model.Destroy(#desert_eagle)
model.Destroy(#m4)

{
Stop this CLEO-script.
================================================}
0A93: end_custom_thread


Of course this is a bit exaggerated for a short code like this, but when you make a large script, you will be thankful if you need to edit something afterwards, or need to show your code to somebody else to get some help.

This was the first tutorial in this topic about advanced scm coding. If you want to give any feedback, please go to our reaction topic.




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users