#1 21-10-2008 13:15

Jabhacksoul
From: Bay City, Michigan
Registered: 03-09-2008
Posts: 8
Website

My Mission Script Tutorial, Noob to Pro - No CLEO needed

I have been using Sanny Builder 3.04 to edit and modify the MAIN.SCM since late August. Yes, a whole 2 months! Many of you are now scratching you head saying wtf is this JABhacksoul going to teach me? I have been using it forever!!

Well, put your ego on hold and check out my tutorial and you just might see something you like. This is NOT a Sanny or CLEO tutorial but I will be using Sanny as the editor compiler. I will try to stick with the original SASCM and not use the Sanny Opcodes although they operate much the same.

[large]Part 1 - Setting up your work area.[/large]

After installing Sanny Builder, I have myself a complete copy of my GTA SA on in a seperate folder named: "M:\Rockstar Games\GTA San Andreas Modded" so my workarea is set to "M:\Rockstar Games\GTA San Andreas Modded\data\script" and it might sound like overkill but inside this directory I have created a folder called Backup and it contains an original SCM and SCRIPT.IMG

Next I copied the stripped.txt from the "Sanny Builder 3\data\sa" folder and made it read only. I made a text file called snippets.txt where I keep any code I find useful on the internet forums. Now I can load the stripped main and start a new file with it. When making a new file use a name that allows you to remember the mission. Avoid using generic names like Mission05.

[large]Part 2 - Study the MAIN.SCM[/large]

Decompile the MAIN.SCM and keep it available to use as a study guide. Let's look at the various parts and layout.

Part A - The Defined Objects

DEFINE OBJECTS 389
DEFINE OBJECT SANNY BUILDER 3.04	  
DEFINE OBJECT INFO					 // Object number -1
DEFINE OBJECT KEYCARD				  // Object number -2
DEFINE OBJECT AD_FLATDOOR			  // Object number -3

This is models that are being defined as objects in the game. For example the first line tells the program there are 389 objects in this list. The object INFO are those little question mark icon pick ups and they are assigned an object number of 1 by the location in this listing. Adding some unknown object to the top would have the effect of shifting all the objects value up one. So if you plan to add any objects it should be done at the bottom.

Down at line number 759 you can see this:

0107: $2706 = create_object #AD_FLATDOOR at 1833.36 -1995.45 12.5 
 or
$2706 = Object.Create(#AD_FLATDOOR, 1833.36, -1995.45, 12.5)

Where they install about 12 of these flatdoors. Without this code certain doors will be missing in the game.

Part B - The Defined Missions.

DEFINE MISSIONS 135
DEFINE MISSION 0 AT @INITIAL		   // Initial 1
DEFINE MISSION 1 AT @INITIL2		   // Initial 2
DEFINE MISSION 2 AT @INTRO			 // Intro
DEFINE MISSION 3 AT @NONE			  // Video Game: They Crawled From Uranus

These are the games 135 missions and you will notice they start numbering them at zero so they end at 134. The first two missions are not real missions at all they set up a bunch of variables and stats, place guns and other pickups, and just get the game up to start. Mission 2 is ran automatically when you start begin a new game. This is where CJ gets off his plane and is grabbed by Tenpenny. Then you must bike home.

You will notice the next mission is a mini game. Everything you do from shopping, getting a tat, going to the bar and shooting pool are all missions.

Part C - External Script Missions.

DEFINE EXTERNAL_SCRIPTS 78 // Use -1 in order not to compile AAA script
DEFINE SCRIPT PLAYER_PARACHUTE AT @PLCHUTE // 0
DEFINE SCRIPT PARACHUTE AT @PARACH	 // 1
DEFINE SCRIPT BCESAR2 AT @BCESAR2	  // 2
DEFINE SCRIPT BCESAR3 AT @COKEC		// 3

These are just like the missions above but are compiled to the SCRIPT.IMG as a bunch of individual scm files.  For example the parachute is a mini mission and is placed outside the MAIN.SCM read from the SCRIPT.IMG These are some basic things you do from going to the gym or getting a phone call from Cesar about the drugs.

Part D - The MAIN thread or loop

//-------------MAIN---------------
03A4: name_thread 'MAIN'  
016A: fade 0 time 0 
042C: set_total_missions_to 147 
030D: set_max_progress 187 
0997: set_total_respect_points_to 1339 
01F0: set_max_wanted_level_to 6

The main thread starts around line 617 and has a thread ID of 'MAIN' just like a mission thread with one exception; there is no call to end this thread. It continues to loop forever.  Next the fade 0 is to make the screen turn black and the time it takes to turn black in thousandths of a second so 1000 is one second.  To fade up from black we just say fade 1 and give the time.  Then it goes on to set up the stats.

Part E - The Rest

The missions follow the main and are accessed by the code inside the main. Accessing the External scripts are slightly different than the missions contained inside the main.scm but now let's look at a stripped scm.

[large]Part 3 - The Stripped Main[/large]

DEFINE MISSIONS 0
//DEFINE MISSION {ID} 0 AT {LABEL} @
DEFINE EXTERNAL_SCRIPTS 0 // Use -1 in order not to compile AAA script
//DEFINE SCRIPT {NAME}  AT {LABEL} @
DEFINE UNKNOWN_EMPTY_SEGMENT 0
DEFINE UNKNOWN_THREADS_MEMORY 0

{$VERSION 3.0.0000}
var
 $PLAYER_CHAR: Player
end // var 
03A4: name_thread 'MAIN' 
01F0: set_max_wanted_level_to 6 
0111: toggle_wasted_busted_check 0 
00C0: set_current_time_hours_to 8 minutes_to 0 
04E4: unknown_refresh_game_renderer_at 2488.56 -1666.84 
03CB: set_rendering_origin_at 2488.56 -1666.84 13.38 
0053: $PLAYER_CHAR = create_player #NULL at 2488.56 -1666.84 13.38 
01F5: $PLAYER_ACTOR = create_player_actor $PLAYER_CHAR 
07AF: $PLAYER_GROUP = player $PLAYER_CHAR group 
0373: set_camera_directly_behind_player 
01B6: set_weather 0 
0001: wait 0 ms 
087B: set_player $PLAYER_CHAR clothes_texture "PLAYER_FACE" model "HEAD" body_part 1 
087B: set_player $PLAYER_CHAR clothes_texture "JEANSDENIM" model "JEANS" body_part 2 
087B: set_player $PLAYER_CHAR clothes_texture "SNEAKERBINCBLK" model "SNEAKER" body_part 3 
087B: set_player $PLAYER_CHAR clothes_texture "VEST" model "VEST" body_part 0 
070D: rebuild_player $PLAYER_CHAR 
01B4: toggle_player $PLAYER_CHAR can_move 1 
016A: fade 1 time 0 
04BB: select_interior 0 
0629: change_integer_stat 181 to 4 
016C: restart_if_wasted_at 2027.77 -1420.52 15.99 angle 137.0 town_number 0 
016D: restart_if_busted_at 1550.68 -1675.49 14.51 angle 90.0 town_number 0 
0180: set_on_mission_flag_to $ONMISSION 
0004: $DEFAULT_WAIT_TIME = 250
03E6: remove_text_box 

// put your create_thread commands here

:MAIN_LOOP
0001: wait $DEFAULT_WAIT_TIME ms
00BF: $TIME_HOURS = current_time_hours, $TIME_MINS = current_time_minutes
0002: jump @MAIN_LOOP

That's it, there are some things I want to point out. That op code 087B will dress up CJ otherwise if you left this out he will be in his underwear. The obscure line that reads:

0629: change_integer_stat 181 to 4

Makes it ok to run all over the 4 cities without getting stars on your head. Lowering the value will make travel a pain. If you play this, you will quickly notice how much the MAIN.SCM does in the game.  There will be no pickups so the only weapons are the ones the cops have. There are no bribes but you can beat up enough peds to collect $100 and drive to a paint and spray to get the stars off.  But that's is about it. No gangs, nothing to buy, can't even save, and no real money. Not much fun.

[large]Part 4 - Building your first mission from the stripped main.[/large]

Part A - Save Game Pickup
I am just going to add most of my commands below the stripped main above. In this simple example we are going to make a save game pick up, a weapon pickup, and interact with a ped. 

Starting above the line: ":MAIN_LOOP" I am going to add this:

0213: $My_Save = create_pickup #PICKUPSAVE type 15 at 230.5896 74.5512 1005.0391 
0570: $Marker_Save = create_asset_radar_marker_with_icon 35 at 1560.68 -1675.49 14.51

The first line created a pickup item out of model #PICKUPSAVE this is the spinning blue diskette model you could use any model like a cop bribe.  Type 15 will respawn the 3 numbers that follow are the X Y Z location of the LSPD near the desks.

The second line is a radar icon value 35 makes the disk (safe house) appear on the radar. Notice the Z value of the interior is over 1000 high?  The interiors are nicknamed "Heavens" because you are not really inside the building at all. When you fade out and in the game teleports you not only to a new location but another dimension of the game.  When you enter an interior your radar goes blank and all the icons disappear.

Just because you made a pickup and a way to locate it the game won't save just yet. Now inside the main loop just above the line: 0002: jump @MAIN_LOOP add this:

00D6: if 
0214:   pickup $My_Save picked_up 
004D: jump_if_false @MAIN_SAVE_END
03D8: show_save_screen 
:MY_SAVE_CHECK
0001: wait 0 ms 
00D6: if 
83D9:   not save_done 
004D: jump_if_false @MAIN_SAVE_END
0002: jump @MY_SAVE_CHECK
:MAIN_SAVE_END

The first 3 lines ask if the player has picked up the $My_Save item then it shows the save game screen. The last part simply waits until the game is saved or the user cancels.  The game then saves at this point with the player's location and stats.

Part B - Weapon Pickup

Back up where we added the Save Game pickup we add this line:

0213: $My_Gun = create_pickup #DESERT_EAGLE type 15 at 508.0762 -71.8294 998.7578

This places the Desert Eagle pistol inside the Bar. You will find it near the booth on the left.  Again this doesn't allow you to have the gun.

In the main loop add:

00D6: if 
0214:   pickup $My_Gun picked_up 
004D: jump_if_false @MAIN_GUN_END
0247: load_model #DESERT_EAGLE
038B: load_requested_models 
:MY_GUN_CHECK
0001: wait 0 ms 
00D6: if 
0248:   model #DESERT_EAGLE available 
004D: jump_if_false @MY_GUN_CHECK
01B2: give_actor $PLAYER_ACTOR weapon 24 ammo 85  
:MAIN_GUN_END

Now at this point you can actually save the game and get a real cool pistol in a bar with 85 rounds of ammo. Now that you picked up a weapon the mission will be simple "Kill a Pedestrian".

We are going to make a standard mission marker below the line you added the gun pickup.

02A7: $Marker_Mission = create_icon_marker_and_sphere 47 at 2073.5681 -1620.5205 13.5469
$ONMISSION = 0

Mission marker OPcode 02A7 shows the icon on the radar at all times until you begin the mission. Again the fist number is the icon design and the 3 remaining are X Y and Z location. 47 is Zero's Mission but I could have used any.

Now in the main loop we cut to the mission thread like this:

00D6: if and
0038:   $ONMISSION == 0 
00ED:   actor $PLAYER_ACTOR 0 near_point 2073.5681 -1620.5205 radius 1.0 1.0 on_foot 
004D: jump_if_false @MAIN_MISSION_END 
0417: start_mission 0 
:MAIN_MISSION_END

Here two conditions are checked if you omit the on mission check then the mission will run over and over and you could end up with a clone army just prior to the game crashing. The second check is to see if the actor is standing in the mission sphere at X Y.

Up at the very top edit this:

DEFINE MISSIONS 0
//DEFINE MISSION {ID} 0 AT {LABEL} @

to this:

DEFINE MISSIONS 1
DEFINE MISSION 0 AT @KILLONE

At the very bottom we add the new thread:

:KILLONE 
03A4: name_thread 'KILLONE'

This is the first mission thread and threads run with each other. The mission loop is still looping and during this time you can still go to the bar get the gun or go to the police station and save. But remember the game only saves the stats and not the mission.

Now we add this:

$ONMISSION = 1 
:KILL_ME
0001: wait 0 ms
04C4: store_coords_to 1@ 2@ 3@ from_actor $PLAYER_ACTOR with_offset  0.0  0.0  0.0
08E5: get_actor_in_sphere 1@ 2@ 3@ radius 150.0 handle_as 24@
00D6: if 
0019:   24@ > 0
004D: jump_if_false @KILL_ME 
0187: 39@ = create_marker_above_actor 24@
07E0: set_marker 39@ type_to 0
0165: set_marker 39@ color_to 0

The $ONMISSION = 1 line shuts down that start mission otherwise we could have 100 missions running. We get the location of the play and store them in 1@ 2@ and 3@ then look for an ped with a model value greater than 0. 24@ becomes our target and a RED marker is placed over his head. The type 0 is an enemy threat. Type 1 is a friend.

 
:KILL_LOOP
0001: wait 0 ms 
00D6: if 
0112:   wasted_or_busted  
004D: jump_if_false @KILL_CHECK
0002: jump @KILL_END

This checks to see if you got killed or arrested on the mission.

:KILL_CHECK
00D6: if 
0118:   actor 24@ dead 
004D: jump_if_false @KILL_LOOP

Meanwhile this checks to see if your target is alive

 
:KILL_SUCCESS
01E3: show_text_1number_styled GXT 'M_PASS' number 2000 time 5000 style 1 
0109: player $PLAYER_CHAR money += 2000 
0164: disable_marker $Marker_Mission
0164: disable_marker 39@

This shuts down the markers and gives you $2000.

:KILL_END
00D8: mission_cleanup 
004E: end_thread

And finally we end the mission by cleaning it up and destroying the thread. Try compiling what you have and above all else study the code.  I am attaching the working demo.txt to this tutorial.  I hopes this helps you understand the San Andreas mission code.



JAB B)

Last edited by Jabhacksoul (21-10-2008 13:27)


Modding the world and making it better!
cnzgcsngkhsktmsoqjjtbysddpvabt.jpg

Offline

#2 26-10-2008 12:19

XotaBi4b
From: Харьков
Registered: 13-09-2008
Posts: 87

Re: My Mission Script Tutorial, Noob to Pro - No CLEO needed

Спасибо.
Thanks.

Offline

Board footer

Powered by FluxBB