为主的祥助 发表于 2012-4-7 09:44:29

【CLEO教学系列】CLEO脚本教程(未完工)

本帖最后由 【游骑兵】天涯 于 2012-4-14 08:56 编辑

翻译:【游骑兵】天涯
原帖地址:http://www.gtaforums.com/index.php?showtopic=403594
初次接触翻译 纰漏之处 在所难免 望指正
建议前往英文站看英文原文 便于理解
注:目前正在汉化中,没有审核已汉化部分,所以请勿过分相信已翻译部分 待翻译完毕+后期审核完毕后请再次查看
由于小道时间不够 手机上论坛常挂 所以正在使用手机Word编辑软件编辑要翻译的内容(汗 手机打字翻译好辛苦)--意思是 近期 此贴将不会更新 完工后更新 sorry for my bad chinese
                                                                                             未经许可 谢绝转载
______________________________________________________________________________________
       ______________________________________________________________________________________

使用Sanny Builder(以下简称SB)进行CLEO脚本编写的第一步:
下载最新版本的Sanny Builder: http://sannybuilder.com/
或者下载【下载】SB汉化版+最小启动包 有汉化版SB
下载地址:http://game.55660.net/thread-138-1-1.html
安装SB并为你的脚本文件创建一个目录
因此你可以选择到你的游戏目录(此句不明)
然后启动SB
打开一个新的空白页面
复制如下脚本源码并把它插入到新的页面







CODE
{$CLEO .cs}
:DEMOTEXT
03A4: name_thread "DEMO"
wait 1000

:DEMOTEXT_1
wait 0
if
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @DEMOTEXT_1
if
00E1:   key_pressed017
004D: jump_if_false @DEMOTEXT_1
00BA: text_styled 'FEM_OK'1000 ms1
0A93: end_custom_thread


把它保存到你刚才创建的脚本文件文件存放目录并且重命名

http://pic.qnpic.com:83/r.jsp?fn=//akatsuki0/share/2012/4/7/88bcae30274405.gif
编译这个脚本 点击菜单上奔跑的人形图标来执行编译+复制操作
如果已经安装过CLEO library 这个脚本文件会被编译并且复制到游戏目录/CLEO目录(前提是安装过CLEO主程序)
{$CLEO .cs} = Cleo 指令会被编译为 以*.cs为后缀的格式文件
而DEMOTEXT.txt 会被保存 并且编译为 DEMOTEXT.cs
______________________________________________________________________________________

如果CLEO主程序没有安装,在SB的右下角处会有红色的安装提示.点击此处SB会快速安装完成.(此处不明 不知道是什么情况 SB自动安装CLEO主程序?)
也可以前往 http://cleo.sannybuilder.com下载最新版CLEO主程序安装器
______________________________________________________________________________________

如果编译成功完成,你会看到如下提示框




http://pic.qnpic.com:83/r.jsp?fn=//akatsuki0/share/2012/4/7/1.gif
点击OK确定
最下面的部分 Largest Script显示的是脚本文件大小
其他的部分属于Main.scm的编译信息
进入游戏测试此脚本,点击0键或Ctrl键按键来显示TEXT的文本信息
这个脚本执行结束,会被收起(不明)因为此脚本是以opcode 0A93: end_custom_thread
而结束。
______________________________________________________________________________________
______________________________________________________________________________________

编辑器
主要的功能可以在菜单栏的相关按钮处找到
1. 汇编: SB打开如下几种脚本文件扩展名 .CS, .CM or .SCM

2. 编译: SB 编译 通过默认(不明)一个 main.SCM

SB自动编译CLEO脚本文件, 如果这个脚本 有一个Cleo-Direktive 作为入口
{$CLEO .cs} = Cleo-Direktive, 会被编译为 .CS后缀名的文件
{$CLEO .cm} = Cleo-Direktive, 会被编译为.CM后缀名的文件


http://pic.qnpic.com:83/r.jsp?fn=//akatsuki0/share/2012/4/7/2.gif








有用的小工具
选择菜单栏上的Tools选项 IDE tools--Coords Manager
读取X Y Z coordinate(不明)和主角CJ的当前方位的方位角(前提是游戏运行)
选择菜单栏上的Tools选项 IDE tools--Opcode Search
来搜索Opcode
输入任何字符来寻找包含这个字符的句子
或者输入Opcode来搜索这类型的句子
搜索结果存在于原版main.scm中
这个Opcode搜索工具需要在 Sanny Builder 3\data\sa folder下创建一个Opcode.txt文本
用SB加载汇编的原版 main 然后选择SB的工具栏, 制作Opcode.txt.

行号
选择Tools(工具)--Option(选项)
在选项 编辑栏 你可以找到开关行号显示的选项
行号是编辑器的一部分,不是脚本的内容。

SB帮助文本
选择菜单栏的帮助文本, 然后按照需要查找信息。,
比如键位, 武器编号, 身体部分等等..

http://thumbnails16.imagebam.com/3028/276a9d30274411.gif

______________________________________________________________________________________
______________________________________________________________________________________



选项: different view of the decompiled code

选择 TOOLS(工具), option(选项)
Option(选项)整体 你可以看见不同的编译方法(不明)

http://thumbnails14.imagebam.com/3028/c1af3130274408.gif


1. 编写Opcode
所有条目以Opcode显示
Opcode是脚本功能的程序编码
他们看起来就像是命令指令
带有Opcode的脚本:


CODE
:CARSL_6439
00D6: if
00E1:   player 0 pressed_key 16
004D: jump_if_false @CARSL_6535
010B: 5@ = player $PLAYER_CHAR money
00D6: if
002D:   5@ >= 14@ // (int)
004D: jump_if_false @CARSL_6512
0012: 14@ *= -1
0109: player $PLAYER_CHAR money += 14@
0002: jump @CARSL_6700


2. 不使用Opcode
脚本更加小, 可能更加清晰
特别是004D: jump_if_false 可以简写为jf
但并不是所有Opcode不使用. 更多编码会被广泛的使用以此运行相应的功能
Script without opcodes:


CODE
:CARSL_6439
if
00E1:   player 0 pressed_key 16
jf @CARSL_6535
5@ = Player.Money($PLAYER_CHAR)
if
002D:   5@ >= 14@ // (int)
jf @CARSL_6512
14@ *= -1
Player.Money($PLAYER_CHAR) += 14@
jump @CARSL_6700


你使用还是不使用Opcode并不会有什么影响
SB还是会正常编译

一个不使用Opcode汇编额特殊方法是把Opcode Based命令翻译为
Classes 和 Keywords

详情参阅Sannybuilder-帮助主题文件: Coding >> Classes

下面是使用Opcode编译的代码:
00AB: put_car 22@ at -1577.942 52.6333 40.0

此句不使用Opcode就如下显示:

Car.PutAt(22@, -1577.942, 52.6333, 40.0)

编码的意义 by the class entries(不清楚)

Car= 类-name
PutAt= 类-member
name and member are combined with a dot in the middle(不明)
22@ = class-owner
class-owner and parameters are placed in brackets and separated with comma
(parameter = needed information for the command)--此段不清晰 望翻译




SB可以使用Keywords(关键词)来替代Opcode
Opcode = Keyword
_____________
0001: = wait
00d6: = if
004d: = else_jump
004d: = jf
0002: = jump
0051: = return
0050: = gosub
016a: = fade
01B6: = set_weather
03a4: = thread
04BB: = select_interior
0417: = start_mission
00d8: = mission_cleanup
0317: = increment_mission_attempts


004D: jump_if_false @MAIN_6
可以写为
jf @MAIN_6
或者else_jump @MAIN_6
你还可以合并为
004D: jf @MAIN_6


______________________________________________________________________________________
______________________________________________________________________________________


Data types(数据类型)


: (doublepoint) marks a Label (adress)--不明


CODE
:MAIN_1


@ 有2种不同功能
1. 跳转到相应的标签

CODE
004D: jump_if_false @SAVE_5
0050: gosub @SAVE_14
0002: jump @SAVE_1


2.链接局部变量
游戏中的物件需要 一个类似身份登记的办法 来处理
执行
这个身份登记可以理解为 变量,
局部变量由@和数字组合而成
0@, 1@, ... 30@ 从
0@ 到 31@ 是允许的 , 32@ 和33@ are for timers, thats maximum in an .cs file(不懂此处作用 等kami)
如下
1@ 定义 一个车辆的创建产生

CODE
014B: 1@ = init_parked_car_generator #PCJ600 0 17 1 alarm 0 door_lock 0 0 10000 at 2490.0 -1682.0 13.5 angle 90.0

1@ 还可以用作局部变量名称(此处指代替这辆车)
CODE
014C: set_parked_car_generator 1@ cars_to_generate_to 101



$ 用来链接全局变量
游戏中的物件需要 一个类似身份登记的办法 来处理
执行
这个身份登记可以理解为 变量
全局变量是以$ 为标志和一些单词,数字之类组成的
在CLE脚本中使用全局变量会导致游戏BUG和崩溃
只有 $PLAYER_CHAR, $PLAYER_ACTOR, $ONMISSION 才是有效地

全局, 局部, 何解?
全局变量运用于Mani.scm中以此在不同游戏线程中相互连接
局部变量同样也是运用于main.scm中但是他们不能在不同游戏线程中相互连接
你可以在线程中用局部变量创建一辆汽车标记为1@同时在main.scm的其他线程中使用1@
1@ = create_car
你有2种不同的车辆,存在于不同的线程命令中

你可以在一个线程中使用全局变量创建一辆汽车但是不在其他线程中再次使用同一个全局变量来创建这辆汽车
$mycar5 = create_car
但是你可以从main.scm的其他线程中调用这辆汽车
全局变量是可储存的,而局部变量则不行
但是在CLEO脚本中使用全局变量会导致游戏BUG和崩溃
只有 $PLAYER_CHAR, $PLAYER_ACTOR, $ONMISSION 才不会



#作为加载模型名称的接入口标志



CODE
0247: load_model #BMYCG
0247: load_model #HMYCM
0247: load_model #SWATVAN
0247: load_model #M4
0247: load_model #COLT45

CLEO只能调用已经定义存储于vehicles.ide, peds.ide or default.ide的内容
其他的模型需要使用他们的ID编号

'...' 短型字符串是用来插入字母或编号 就像GTX entrynames 或者特殊 IPL entries的名称

CODE
03A4: name_thread 'MAIN'
0917: audio_zone 'BEACH' enable_sound 0
00BA: show_text_styled GXT 'INTRO_1' time 1000 style 2
0299: activate_garage 'MODLAST'
07FB: set_interior 'GYM1' access 1// Ganton Gym
0390: load_txd_dictionary 'LD_BEAT'
076C: set_zone 'GAN1' gang 1 density_to 25


"..."长型字符串是用来插入字母或编号比如动作-IFP 文件名称, 身体部位名称, particel 名称, 等待
CODE
087B: set_player $PLAYER_CHAR clothes_texture "PLAYER_FACE" model "HEAD" body_part 1
038F: load_texture "DOWN" as 1 // Load dictionary with 0390 first
0605: actor -1 perform_animation_sequence "DAN_LOOP_A" IFP_file "DANCING" 4.0 loop 1 0 0 0 time -1 // versionA
0674: set_car_model #GREENWOO numberplate "GROVE4L_"
0245: set_actor 5@ walk_style_to "GANG2"
064B: 25@ = create_particle "EXPLOSION_MOLOTOV" at 2010.0 -1610.0 16.5 type 1


To set entries of strings equal to variable names must be used special opcodes and extended variable signs设定线程接入口(或者说变量名称)必须使用特殊的Opcode和扩展变量标志( extended variable signs)------不确定

05AA:
05A9:
06D2:
06D1:
furthermore can strings also replaced with variables by using extended variable signs
此外线程可以取代变量通过使用扩展变量标志--(不确定)
@s - local-string-variable(局部线程变量)

CODE
05AA: 5@s = 'FEM_OK'
00BC: show_text_highpriority GXT 5@s time 10000 flag 1


s$ - global-string-variable(全局线程变量)
注意在CLEO脚本中使用全局变量 会导致游戏BUG或者崩溃
CODE
05A9: s$Actor_Speech_GXT_Reference = 'CATX_UA'// ~z~Carl, you are a f*cking idiota!                  
00BC: show_text_highpriority GXT s$Actor_Speech_GXT_Reference time 10000 flag 1
05AA: 5@s = s$Actor_Speech_GXT_Reference
00BC: show_text_highpriority GXT 5@s time 10000 flag 1


@v - local-long-string-variable(局部长型线程变量)

CODE
06D2: 28@v = "LAPDAN1" // @v = string
0812: AS_actor $PLAYER_ACTOR perform_animation "LAPDAN_P" IFP_file 28@v 1000.0 loopA 0 lockX 0 lockY 0 lockF 1 time -1


v$ - global-long string-variable(全局长型变量)
注意在CLEO脚本中使用全局变量 会导致游戏BUG或者崩溃
CODE
06D1: v$1225 = "Bat_block"// 16-byte strings                  
0605: actor $PLAYER_ACTOR perform_animation_sequence v$1225 from_file "BASEBALL"4.01000 -1 ms



______________________________________________________________________________________
______________________________________________________________________________________


Scripting/Writing a Thread(不明)

在游戏中运行的脚本叫做线程
他们是用create_thread命令或者一个定义任务的脚本定义于Main.scm中作为线程

The cleo programm checks if there is .cs file in the Cleo folder
and if yes, it start this script as threadCLEO程序会扫描CLEO目录是否存在CS文件
如果存在,游戏就会加载这个CLEO脚本。

Script structur / short version:(不知道)

首先,在开头,会以CLEO指令开始


CODE
{$CLEO .cs}

First Label (adress)

CODE
:Akt

然后给线程定义一个名称
CODE
03A4: name_thread 'AKT'

现在写入一个代码然后用end_custom_thread 结束线程
一切OK后进游戏测试


CODE
{$CLEO .cs}
:Akt
03A4: name_thread 'AKT'
08B2: toggle_thermal_vision 1
0A93: end_custom_thread

Script above activates the Infrarot view unless in cutscenes(不知道)
脚本会以opcode 0A93: end_custom_thread结束
The script will be started by each loading of savegame or by start new game
这个脚本会在每次加载存档运行或者开启新游戏后运行

______________________________________________________________________________________



下一步/使用环境条件检查

一个环境条件检查需要最少3个Opcode

1. IF 条件
2. 真正情况
3. 反向跳转设置


1. if

2. 0AB0: key_pressed 8

3. 004D: jump_if_false @akt_01


我们再次使用先前的脚步但是现在我们想要切换到正常模式因此我们使用一个环境检查,建立一个循环

Loop means that a jump instruction can send the reading process to a previous adress
I call such an adress "Loop-adress"循环意味着一个跳转命令可以传达信息到先前的地址 我把它叫做循环地址(Loop-adress)--不确定

在这样一个循环跳转后必须等待XXX毫秒
跳转指令可以是反向跳转或者正向跳转


CODE
004D: jump_if_false @akt_01

or

CODE
0002: jump @akt_01



对于如下脚本的按键环境检查是通过按Backspace键执行的

CODE
{$CLEO .cs}:Akt03A4: name_thread 'AKT'08B2: toggle_thermal_vision 1:Akt_01//----------------------------Loop adresse0001: wait 0 msif0AB0: key_pressed 8004D: jump_if_false @Akt_01//--------jump instruction by negation08B2: toggle_thermal_vision 00A93: end_custom_thread

Script above activates the Infrarot view and toggle back to normal view by key_press
The reading process is looping as long as BACKSPACE is not pressed
the jump instruction by negation sends the reading process allways to the label :Akt_01
1000 times per second

______________________________________________________________________________________



The IF - Variation

CODE
if00FF: actor $PLAYER_ACTOR 1 (in-sphere)near_point_on_foot 2493.5 -1682.5 13.35 radius 1.0 1.0 1.0004D: jump_if_false @Teleport_2



By more than one question in an conditional check requires to determine,
if it means if or or if and


CODE
if and
00DF:   actor $PLAYER_ACTOR driving
8119:   NOT   car 0@ wrecked
004D: jump_if_false @AD_5


CODE
if or
00E1: key_pressed 0 0
00E1: key_pressed 0 1
00E1: key_pressed 0 14
00E1: key_pressed 0 18
004D: jump_if_false @AD_7


CODE
if or
8118:   NOT   actor 7@ dead
8118:   NOT   actor 8@ dead
004D: jump_if_false @AD_25
0002: jump @AD_12


The most question codes can be changed into the opposite question
by changing the ciro of the opcode into 8 and insert "not" into the code line

exemble:

CODE
00E1: key_pressed 0 10

and

CODE
80E1: NOT key_pressed 0 11


______________________________________________________________________________________



Next Step/ Script structure simple

The previous scripts ended because of the opcode 0A93: end_custom_thread
Instead let the script ending we use a jump instruction at script end to the 1.Loop adress
So the reading process is permanent looping

CODE
0002: jump @Akt_01

And since now we add a check in our loop which we add allways after a Loop adress.
It is:

CODE
if
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @Akt_01

It should prevent crashes if the player dies or gets arrested
The "IF Player- Defined-check" should allway be the first check in a loop

Script structure simple with 1 Loop:
-Script head
-1.Loop-Adress
-wait code
-IF player_defined-check
-Conditional Check
-Event
-Normal jump instruction to 1.LoopAdress


CODE
{$CLEO .cs}
:Akt
03A4: name_thread 'AKT'

:Akt_01
0001: wait 0 ms
if
0256: player $PLAYER_CHAR defined
004D: jump_if_false @Akt_01
if
0AB0:   key_pressed 8//-----------------key = Backspace
004D: jump_if_false @Akt_01
08B2: toggle_thermal_vision 1
0001: wait 3000 ms
08B2: toggle_thermal_vision 0
0002: jump @Akt_01//--------Normal jump instruction to 1.LoopAdress

Script above activates the Infrarot view after key_press
and toggle back to normal view after 3 seconds

______________________________________________________________________________________



Next Step/ Script structure extended

To start an event with our script will change the game state and the conditions.
This needs to redirect the reading process to prevent that the same code will be read again.
Therefore we add a second Loop in the script
Loop 1 - before the event
Loop 2 - after the event

Script structure extended with 2 Loops:
-Script head
-1.Loop-Adress
-wait code
-IF player_defined-check
-Conditional Check
-Event
-2.Loop-Adress
-wait code
-IF player_defined-check
-Conditional Check
-Normal jump instruction to 1.LoopAdress


CODE
{$CLEO .cs}
:akt
03A4: name_thread 'AKT'

:akt01//----------------------------1.Loop Adress
0001: wait 0 ms
if
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @akt01
if
00DF:   actor $PLAYER_ACTOR driving
004D: jump_if_false @akt01

03C0: 1@ = actor $PLAYER_ACTOR car
0229: set_car 1@ color_to 17 0
02AC: set_car 1@ immunities BP 1 FP 1 EP 1 CP 1 MP 1
053F: set_car 1@ tires_vulnerability 0


:akt03//----------------------------2.Loop Adress
0001: wait 0 ms
if
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @akt03
if
80DF:   not actor $PLAYER_ACTOR driving
004D: jump_if_false @akt03

01C3: remove_references_to_car 1@

0002: jump @akt01//--------Normal jump instruction to 1.LoopAdress

The script above makes the player_car undestructable as soon as a car is entered
Therefore we must registrate the instance of the car and define it with a variable name
03C0: 1@ = actor $PLAYER_ACTOR car
Then we can use this variable name 1@ to make the car immun

After player has left the car, the reading process jumps back into the first Loop.

Youre not restricted by 2 Loops and there are also other kinds of script structure
But I recommand to build your scripts with this structure as long as you have not much experience

http://zazmahall.de/ZAZGTASANATORIUM/zazmodpics/EngScript_LOOP.jpg


______________________________________________________________________________________



Script exemble: Slowmotion

The script toggle by key_press between slowmotion and normal speed
set_gamespeed .3 make the game slow and also the reading process
wait 50 milliseconds needs ca. 1 second
A "if_player_defined"-check is not nessesary because the script dont have any codes which belongs to the player
After a passed key_press check it makes sense to set a wait of one second otherwise the key_press check will be repeated to fast.


CODE
{$CLEO .cs}
:slow_0
03A4: name_thread 'SLW'

:slow_1
0001: wait0 ms
if
0AB0:   key_pressed 8//-----------------key = Backspace
004D: jump_if_false @slow_1
015D: set_gamespeed.3
0001: wait50 ms

:slow_2
0001: wait0 ms
if
0AB0:   key_pressed 8//-----------------key = Backspace
004D: jump_if_false @slow_2
015D: set_gamespeed1.0
0001: wait1000 ms
0002: jump @slow_1


______________________________________________________________________________________



Next Step/ Spawn a 3D model

Using models requires 5 steps by applying with models and their definition in its variable name

1. first step to load the model

CODE
0247: request_model #INFERNUS

2. second step to prove if the model is loaded in an extra "load-model-check-Loop"

CODE
:Load_Model_Check
0001: wait0 ms
00D6: if0
0248:   model #INFERNUS available
004D: jump_if_false @Load_Model_Check

3. The model can be created as soon as the model file is loaded and define it with a variable name

CODE
00A5: 1@ = create_car #INFERNUS at 2487.5-1660.513.35
0175: set_car 1@ z_angle_to 90.0

4. release the loaded model file if it not needed anymore

CODE
0249: release_model #INFERNUS

5. Release the defined item from script when the script has done its work
The script can then go to the status quo by jumping back into the first Loop

CODE
01C3: remove_references_to_car 1@// Like turning a car into any random car

Releasing a spawned car by using 01C3: remove_references_to_car deletes the instance of the car for our script
but its still available in the game but can not used anymore in our script.

An other way to release the car is to delete it complete:

CODE
00A6: destroy_car 1@


This 2 different kinds for releasing exist for vehicles, actors and objects each with own opcodes


CODE
{$CLEO .cs}
:3dModels_1
03A4: name_thread 'MODL'

:3dModels_2
0001: wait0 ms
00D6: if0
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @3dModels_2
00D6: if0
00FF:   actor $PLAYER_ACTOR1 (in-sphere)near_point_on_foot 2491.5-1667.513.35 radius1.01.01.0
004D: jump_if_false @3dModels_2

0247: request_model #INFERNUS

:Load_Model_Check
0001: wait0 ms
00D6: if0
0248:   model #INFERNUS available
004D: jump_if_false @Load_Model_Check

00A5: 1@ = create_car #INFERNUS at 2487.5-1660.513.35
0175: set_car 1@ z_angle_to 90.0
0249: release_model #INFERNUS

:3dModels_3
0001: wait0 ms
00D6: if0
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @3dModels_3
00D6: if0
80FF:   NOT   actor $PLAYER_ACTOR0 ()near_point_on_foot 2491.5-1667.513.35 radius2.02.02.0
004D: jump_if_false @3dModels_3
01C3: remove_references_to_car 1@// Like turning a car into any random car
0002: jump @3dModels_2

Script above spawns the car Infernus in Grovestreet if player goes into red marker(sphere)
If player leave the spot the car will be released from script and the reading process jumps back into 1.Loop


# marks the connected entry as filename of a loadable model
For Cleo can only be used models which are defined in vehicles.ide, peds.ide or default.ide
Other models needs to use their ID number

For exemble to spawn the object 1655, waterjumpx2 of data\maps\generic\multiobj.ide

CODE
{$CLEO .cs}
:JumpR00
03A4: name_thread 'JPR'

:JumpR01
0001: wait0 ms
00D6: if 0
0256: player $PLAYER_CHAR defined
004D: jump_if_false @JumpR01
00D6: if0
00E1:   key_pressed010//--------- No key
004D: jump_if_false @JumpR01
0247: request_model 1655

:JumpR02
0001: wait0 ms
00D6: if0
0248:   model 1655 available
004D: jump_if_false @JumpR02
0172: 2@ = actor $PLAYER_ACTOR z_angle
04C4: create_coordinate 11@ 12@ 13@ from_actor $PLAYER_ACTOR offset 0.0 14.5 -1.8
0107: 1@ = create_object 1655 at11@ 12@ 13@
0177: set_object 1@ z_angle_to2@
0001: wait0 ms
0249: release_model 1655
0001: wait1000 ms
01C4: remove_references_to_object 1@// This object will now disappear when the player looks away
0002: jump @JumpR01

Script above spawns a jumpramp by key_press

You can allways use the ID number to spawn models, also for cars and actors
As next we use 120 intead #TRIBOSS to spawn an actor


CODE
{$CLEO .cs}
:Actor_1
03A4: name_thread 'Actor'

:Actor_2
0001: wait0 ms
00D6: if0
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @Actor_2
00D6: if0
00FF:   actor $PLAYER_ACTOR1 (in-sphere)near_point_on_foot 2491.5-1667.513.35 radius1.01.01.0
004D: jump_if_false @Actor_2

0247: request_model 120
0247: request_model #AK47

:Load_models_check
0001: wait0 ms
00D6: ifand
0248:   model 120 available
0248:   model #AK47 available
004D: jump_if_false @Load_models_check

009A: 1@ = create_actor24 120 at2486.5-1664.513.45
0173: set_actor 1@ z_angle_to180.0
01B2: give_actor 1@ weapon30 ammo99999// Load the weapon model before using this
02E2: set_actor 1@ weapon_accuracy_to100
0223: set_actor 1@ health_to1000
05E2: AS_actor 1@ kill_actor $PLAYER_ACTOR
0249: release_model 120

:Loop_1
0001: wait0 ms
00D6: if0
8118:   NOT   actor 1@ dead
004D: jump_if_false @Cleanup_1
00D6: if0
0104:   actor $PLAYER_ACTOR near_actor 1@ radius80.080.010.0 sphere0
004D: jump_if_false @Cleanup_1
0002: jump @Loop_1

:Cleanup_1
01C2: remove_references_to_actor 1@ // Like turning an actor into a random pedestrian
0002: jump @Actor_2

Script above spawns the actor Triboss with gun in Grovestreet
If player leave the area with radius 80.0 80.0 or if the actor is dead,
the actor will be released from script and the reading process jumps back into 1.Loop

To give the actor or the player a weapon requires also to load first the model file
But to give it then really into his hands needs to insert a special weapon number which is not documented in any game file.
To find the right weapon number look in Sannybuilder HELP: SCM Documentation >> GTA SA >> Weapon numbers

Weapon given to actors are not created in same sense like the other models,
so it dont it to release them from script like other items

The spawned actors have predefined execodet behaviors which is dependent by the pedtype parameter of the create_actor opcode.
Look for pedtypes in Sannybuilder HELP: SCM Documentation >> GTA SA >> PedTypes

An actor with pedtype 8 is recruitable like a homie

CODE
009A: 1@ = create_actor8 #TRIBOSS at2486.5-1664.513.45

An actor with pedtype 7 is agressive like an enemy gangmember

CODE
009A: 1@ = create_actor7 #TRIBOSS at2486.5-1664.513.45


______________________________________________________________________________________



Placing cars by using parked_car_generator

Init parked_car_generators or pickups need to insert the Cleo opcode:

0A95: enable_thread_saving

Read the discription about enable_thread_saving in the theme:
Special Particularities in Cleo >> Registrate (store) the Script State

The placing of cars by using parked_car_generator dont allows the using of its variable name in vehicle associated opcodes
because its not a car but a car_generator


CODE
{$CLEO .cs}
:PaCar_1
03A4: name_thread "PACR"
0001: wait1000 ms
0A95: enable_thread_saving

014B: 1@ = init_parked_car_generator #BANSHEE -1 -11 alarm0 door_lock0010000 at920.19942020.54611.79 angle100.0
014C: set_parked_car_generator 1@ cars_to_generate_to101

032B: 2@ = create_weapon_pickup #MINIGUN15 ammo5000 at2113.373 1520.67410.82

0A93: end_custom_thread

Script above adds a parked_car_generator to spawn the car Banshee
and a weapon pickup with MINIGUN


generate_to 101 means that the car will be spawned again and again
generate_to 0 deactivates the car_generator

the two parameters after the model name -1 -1 gives the secondary and primary color
by setting -1 -1the game choose the colors randomly

by setting 0 17 it give black (0) to primary and red (17) to secondary color

alarm 0 can be a value between 0 and 100 and means the probable chance to execute an alarm

door_lock 0 can be a value between 0 and 100 and means the probable chance to execute a door lock


For pickups exist 2 different opcodes for 2 different kinds of pickups
032B: for weapons with ammo and for the Jetpack
0213: for melee weapons and objects like parachute (GUN_PARA) or bodyarmour (1242, bodyarmour)
the parameter after the model ID #MINIGUN 15 is the pickup-typ
Typ 15 is a pickup, which appears again and again
Typ 3 is a pickup, which appears only for one time


______________________________________________________________________________________
______________________________________________________________________________________




Special Particularities in Cleo

The extra-Cleo opcodes can be found in Sannybuilder-HELP
CLEO 3 Code Library >> CLEO 3: opcodes CLEO 3 Code Library>> CLEO 3: opcodes

______________________________________________________________________________________


Two major codes to start scripts are those which already exist in the main.scm and have been re-created for Cleo:

1.) 004F: create_thread @SAVEGAME starts an ordinary thread in the main.scm.
We dont need it in Cleo because it will be allready started from Cleo programm
To start an other thread of a cleo script, started from a cleo script needs following opcode:

0A92: create_custom_thread "New_Test_thread.cs"

The code needs to insert the name of the script file which should get started inclusiv dot and extension

The Cleo script file get then the file extension, which is written in the Cleo Script directive at the beginning of the script
{$CLEO .cs} = Cleo directive will be compiled to *.cs
As New_Test_thread.txt saved and compiled as New_Test_thread.cs

The script get then started at second once. Once from Cleo programm and once from the 0A92: create_custom_thread
It needs to set a conditional check at script beginn to let the script ending when it was started from Cleo programm.

An other chance is to give the script the extension .s
This needs to insert following:

0A92: create_custom_thread "New_Test_thread.s"

The Cleo script file which should get started, must have {$CLEO .cs} as directive and will be compiled as *.cs
You must change the extension manual by renaming from *.cs into *.s
In this case the Cleo script will only run if it was started with 0A92: create_custom_thread from an other Cleo script.

The opcode 0A92: create_custom_thread can transport more information to the script which should be started
This opcode can be extended with up to 30 values or variables as parameters
exemble:

CODE
0A92: create_custom_thread "PimpmyCarFULL2A1.cs" 1 2 0 3@ 4@ 5@ 6@ 29@ 8@ 9@ 10@

The started thread recieves these parameter values with following rule
0@ get value of 1.parameter
1@ get value of 2.parameter
2@ get value of 3.parameter
3@ get value of 4.parameter
4@ get value of 5.parameter
etc...
Its also possible to start much threads in one and the same Cleo script, started from the same script which recieve the create_thread commands.


2.)

0417: start_mission 3
starts a mission script of the main.scm. It needs to insert the number which the mission script get from the listing of the mission table

In Cleo dont exist a mission table and its listing.
But it needs allways a Cleo mission starter script with following command:

0A94: start_custom_mission "DriftMission"

The code needs to insert the name of the script file which should get started but without extension

The Cleo script file get then the file extension, which is written in the Cleo Script directive at the beginning of the script
{$CLEO .cm} = Cleo directive will be compiled to *.cm
As DriftMission.txt saved and compiled as DriftMission.cm

______________________________________________________________________________________


0A93: end_custom_thread let a script ending. Its disabled then.

The original version of this code of the main.scm is 004E: end_thread

And this original version must be used furthermore in Cleo mission scripts (*.cm)

004E: end_thread

Again:

0A93: end_custom_thread in normal Cleo scripts, compiled to a *.cs file

CODE
{$CLEO .cs}
0A93: end_custom_thread


004E: end_thread in mission scripts, compiled to a *.cm file

CODE
{$CLEO .cm}
004E: end_thread


______________________________________________________________________________________


Cleo creates extra save files if a save was done,
stored in folder CLEO\Cleo_save

By loading a save file must taken care to check that the presence of the scripts in Cleo folder
is the same as it was as the save was done.
Special attention in this case are going to those scripts which includes the Cleo opcode
to registrate and store the Script State

______________________________________________________________________________________



Registrate (store) the Script State

The Cleo scripts with extension .cs are started allways from new by loading a save game or start new game,
If such a script includes for exemble a parked car generator and execute it and after this a save game is made,
and then this save game is loaded,
will be created a duplicate of the item, in this case a duplicate of a parked car generator.
This happens with parked car generator, pickups as well as placed objects.

To prevent this or to read the script state by using special special Cleo-variable
must be used following Cleo opcode:

CODE
0A95: enable_thread_saving

This instruct Cleo to store the script state by making a savegame

______________________________________________________________________________________


Special Global Cleo Variable

This theme requires the understanding of the description about Local Variables and Global Variables
of the previous theme Datatype
especially this part which tells why there exist Local Variables and Global Variables
Global Variables are used in main.scm to communicate between different scripts and they are storable.
Using Global Variables in Cleo scripts can cause bugs and crashes

To realize Global Variables for Cleo scripts exist following Cleo opcode connected with a special expression:

Opcode 0AB3: and 0AB4:

The expression var together with a number, <var><space><number> is builing the Special Global Cleo Variable


CODE
0AB3: var 0 = 10
or
0006: 13@ =10// integer values
0AB3: var 0 = 13@

and
0AB4: 0@= var 0

var 0 up to var 999 will be stored, in exemble var 0 is stored with 10

to get then stored value into your script needs to submit into a local:

CODE
0AB4: 13@ = var 44
if
0039:   13@ ==1// integer values
004D: jump_if_false @nextlabel


______________________________________________________________________________________
______________________________________________________________________________________



Script Exemble by using Special Global Cleo Variable/ Store a car at any place
(requires to understand all previous themes of this tut)

Script below saves a car at any place
If player is in car and key F7 is pressed, it stores x,y,z coords and angle, also the car ID, its primary and secondary color and its paintjob.

The player exit then the car and car will be locked and made immun
If player leave the location and the distance to the car will be greater then 100.0
the car will be released from script and the reading process jumps back into an other Loop

If player then comes back to the location, near 80.0 the car will be spawned as new
Only to store the car settings by making savegame needs to give the values into the Special Global Cleo Variable

As I wrote in the theme "Registrate (store) the Script State"
is the Carstore script running from new by loading a save game or start new game"...

...and checks first if var 955 is ciro
its only not ciro if a car was stored in the loaded savegame

If var 955 is ciro, the script starts with the 1.Loop
If var 955 is not ciro, the reading process jumps into the 3.Loop with the check if player is near the car store location

A special side effect of this kind of car store is that the storable entries then available in memory for all savefiles.
Only by shut down the game and start again is the stored car only stored in the savegame which was done to store the car.


CODE
{$CLEO .cs}
:CARSTORE
03A4: name_thread 'CARSTOR'
0001: wait 1000 ms
0AB4: 7@ = var 955
00D6: if
8039:   not7@ == 0
004D: jump_if_false @CARSTOR_150
0AB4: 3@ = var 951
0AB4: 4@ = var 952
0AB4: 5@ = var 953
0AB4: 6@ = var 954
0AB4: 7@ = var 955
0AB4: 8@ = var 956
0AB4: 9@ = var 957
0AB4: 10@ = var 958
0093: 3@ = integer 3@ to_float
0093: 4@ = integer 4@ to_float
0093: 5@ = integer 5@ to_float
0093: 6@ = integer 6@ to_float
0001: wait 1000 ms
0002: jump @CARSTOR_555

:CARSTOR_150
0001: wait 0 ms
00D6: if
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @CARSTOR_150
00D6: if and
00DF:   actor $PLAYER_ACTOR driving
0AB0:   key_pressed 118//-------------------key F7
004D: jump_if_false @CARSTOR_150
01B4: set_player $PLAYER_CHAR can_move 0
03C0: 2@ = actor $PLAYER_ACTOR car
00AA: store_car 2@ position_to 3@ 4@ 5@
0174: 6@ = car 2@ Z_angle
0441: 7@ = car 2@ model
0988: get_car 2@ paintjob 8@
03F3: get_car 2@ primary_color_to 9@ secondary_color_to 10@
020A: set_car 2@ door_status_to 0
02AC: set_car 2@ immunities BP 1 FP 1 EP 1 CP 1 MP 1
0519: set_car 2@ locked 1
0633: AS_actor $PLAYER_ACTOR exit_car
0092: 13@ = float 3@ to_integer
0092: 14@ = float 4@ to_integer
0092: 15@ = float 5@ to_integer
0092: 16@ = float 6@ to_integer
0AB3: var 951 = 13@
0AB3: var 952 = 14@
0AB3: var 953 = 15@
0AB3: var 954 = 16@
0AB3: var 955 = 7@
0AB3: var 956 = 8@
0AB3: var 957 = 9@
0AB3: var 958 = 10@
0001: wait 2000 ms
01B4: set_player $PLAYER_CHAR can_move 1
0002: jump @CARSTOR_403

:CARSTOR_403
0001: wait 0 ms
00D6: if
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @CARSTOR_550
00D6: if
82BF:   not car 2@ sunk
004D: jump_if_false @CARSTOR_738
00D6: if
8119:   not car 2@ wrecked
004D: jump_if_false @CARSTOR_550
00D6: if
0202:   actor $PLAYER_ACTOR near_car 2@ radius 100.0 100.0 flag 0
004D: jump_if_false @CARSTOR_550
00D6: if
00DF:   actor $PLAYER_ACTOR driving
004D: jump_if_false @CARSTOR_403
00D6: if
00DB:   actor $PLAYER_ACTOR in_car 2@
004D: jump_if_false @CARSTOR_403
02AC: set_car 2@ immunities BP 0 FP 0 EP 0 CP 0 MP 0
0519: set_car 2@ locked 0
0002: jump @CARSTOR_738

:CARSTOR_550
01C3: remove_references_to_car 2@ // Like turning a car into any random car

:CARSTOR_555
0001: wait 0 ms
00D6: if
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @CARSTOR_555
00D6: if
00FE:   actor $PLAYER_ACTOR sphere 0 in_sphere 3@ 4@ 5@ radius 80.0 80.0 50.0
004D: jump_if_false @CARSTOR_555
0002: jump @CARSTOR_624

:CARSTOR_624
0247: load_model 7@

:CARSTOR_629
0001: wait 0 ms
00D6: if
0248:   model 7@ available
004D: jump_if_false @CARSTOR_629
0001: wait 0 ms
00A5: 2@ = create_car 7@ at 3@ 4@ 5@
0175: set_car 2@ Z_angle_to 6@
06ED: set_car 2@ paintjob 8@
0229: set_car 2@ primary_color_to 9@ secondary_color_to 10@
020A: set_car 2@ door_status_to 0
02AC: set_car 2@ immunities BP 1 FP 1 EP 1 CP 1 MP 1
0519: set_car 2@ locked 1
0249: release_model 7@
0002: jump @CARSTOR_403

:CARSTOR_738
01C3: remove_references_to_car 2@ // Like turning a car into any random car
0AB3: var 955 = 0
0002: jump @CARSTOR_150


______________________________________________________________________________________
______________________________________________________________________________________



Template for Cleo Mission Script
(requires to understand all previous themes of this tut)

To run a Cleo mission script requires allways 2 Cleo script files
1. A .cs file to start the Cleo mission script file
2. The Cleo mission script file itself with extension .cm


The mission starter thread below is done with a conditional check to check if the player is near a specified point,
which must passed to start the mission.

The coordinates of the near_point check are the location in San Fierro/Carlton Heights near savehouse
Edit the coordinates to set your own location for starting

The parameter 1 of the near_point opcode 00FE: actor $PLAYER_ACTOR 1 (in-sphere)near_point
is displaying a red marker (sphere).
If the parameter is ciro 00FE: actor $PLAYER_ACTOR 0 (in-sphere)near_point does not displaying a red marker.
To display a red marker in this way needs to set 0ms as maximum in the wait code of this Loop

CODE
{$CLEO .cs}
:Test_M_Start_1
03A4: name_thread 'TSTM'

:Test_M_Start_2
0001: wait0 ms
00D6: if0
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @Test_M_Start_2
00D6: if0
0038:   $ONMISSION ==0// integer values
004D: jump_if_false @Test_M_Start_2

:Test_M_Start_6
00D6: if0
00FE:   actor $PLAYER_ACTOR1 (in-sphere)near_point 2480.1343 -1665.475 13.3348 radius3.53.55.5
004D: jump_if_false @Test_M_Start_2
00BA: text_styled 'STAD_02'1000 ms2
0004: $ONMISSION =1// integer values
0A94: start_custom_mission "TestMission"//
0002: jump @Test_M_Start_2

The mission starter script includes the following Cleo opcode to start the Cleo mission script:
0A94: start_custom_mission "TestMission"

The code needs to insert the name of the script file which should get started but without extension

The Cleo script file get then the file extension, which is written in the Cleo Script directive at the beginning of the script
{$CLEO .cm} = Cleo directive will be compiled to *.cm
As TestMission.txt saved and compiled as TestMission.cm


CODE
{$CLEO .cm}
:TestMiss_1
03A4: name_thread "TESTM"
0050: gosub @TestMiss_main_1
00D6: if0
0112:   wasted_or_busted
004D: jump_if_false @TestMiss_end_1
0050: gosub @TestMiss_fail_1                  

:TestMiss_end_1
0050: gosub @TestMiss_clep_1
004E: end_thread

:TestMiss_main_1
0317: increment_mission_attempts//here starts the missionscript
0004: $ONMISSION =1
054C: use_GXT_table 'MENU2P'
00BC: text_highpriority 'MENU_18'5000 ms1

:TestMiss_11
0001: wait 0 ms
if and
02D8:   actor $PLAYER_ACTOR currentweapon == 0
00E1:   key_pressed 0 17
004D: jump_if_false @TestMiss_11

:TestMiss_pass_1
00BA: text_styled 'M_PASS'5000 ms1
0051: return

:TestMiss_fail_1
00BA: text_styled 'M_FAIL'5000 ms1
0051: return

:TestMiss_clep_1
0004: $ONMISSION =0
00D8: mission_cleanup
0051: return


When the mission script from above is running it can be completed by pressing fire key while player have weapon 0/naked fist.


The secret of the onmission mode

$ONMISSION is not only a variable to check if a mission script is running or not.
Set $ONMISSION to 1 activates a special mission mode if some important conditions are accomplished.
R*s mission scripts run allways in a subroutine which will be cancled from the exe if player is wasted or busted like reading a return code in the script.

1. At first it needs to set $ONMISSION equal to on_mission_flag

CODE
0180: set_on_mission_flag_to $ONMISSION// Note: your missions have to use the variable defined here

This code is set by default in the main part of the original main.scm

2. By starting the mission script must sended the reading precess with a gosub command into a subroutine for the main part of the mission script.
It must be the first gosub of the mission script.

CODE
0050: gosub @TestMiss_main_1


3. By starting the mission script must be activated the onmission mode with

CODE
0004: $ONMISSION =1
0317: increment_mission_attempts//here starts the missionscript


Then the mission is running in a subroutine and dont needs to check if player is defined or dead or busted.
If player dies or get busted, the exe cancels the subroutine as like as a return code of our script is readed

The rest of the mission script is just a cunning gosub construct.

______________________________________________________________________________________
______________________________________________________________________________________



gosub

The gosub command leads the reading process to an excluded subscript.
Excluded means the codes of the subscript are not binded in code following of our thread.

CODE
0050: gosub @MODLSUBROUTINE

The subscript must end with return

CODE
0051: return


If the subscript ends with 0051: return, our thread then continues with reading the codes after the 0050: gosub command

Exemble:

CODE
{$CLEO .cs}
:MODLSUB_1
03A4: name_thread 'MODLSUB'

:MODLSUB_2
0001: wait0 ms
00D6: if0
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @MODLSUB_2
00D6: if0
00FF:   actor $PLAYER_ACTOR1 (in-sphere)near_point_on_foot 2491.5-1667.513.35 radius1.01.01.0
004D: jump_if_false @MODLSUB_2
0050: gosub @MODLSUBROUTINE

:Loop_1
0001: wait0 ms
00D6: if0
8118:   NOT   actor 1@ dead
004D: jump_if_false @Cleanup_1
00D6: if0
0104:   actor $PLAYER_ACTOR near_actor 1@ radius80.080.010.0 sphere0
004D: jump_if_false @Cleanup_1
0002: jump @Loop_1

:Cleanup_1
01C2: remove_references_to_actor 1@ // Like turning an actor into a random pedestrian
0002: jump @MODLSUB_2


:MODLSUBROUTINE
0005: 1@ = 2473.25
0005: 2@ = -1657.79
0005: 3@ = 13.4
0005: 4@ = 2501.12
0005: 5@ = -1676.5
0005: 6@ = 13.4
0208: 7@ = random_float_in_ranges 1@ 4@
0208: 8@ = random_float_in_ranges 2@ 5@
0208: 9@ = random_float_in_ranges 3@ 6@
0247: request_model #TRIBOSS
0247: request_model #AK47

:Load_MODLSUB_Check
0001: wait0 ms
00D6: ifand
0248:   model #TRIBOSS available
0248:   model #AK47 available
004D: jump_if_false @Load_MODLSUB_Check

009A: 1@ = create_actor24 #TRIBOSS at7@ 8@ 9@
0173: set_actor 1@ z_angle_to180.0
01B2: give_actor 1@ weapon30 ammo99999// Load the weapon model before using this
02E2: set_actor 1@ weapon_accuracy_to100
0223: set_actor 1@ health_to1000
05E2: AS_actor 1@ kill_actor $PLAYER_ACTOR
0249: release_model #TRIBOSS
0051: return

Script above spawns the actor Triboss with gun in Grovestreet at different places
The coords are generated random
The part with the coords generation and actor spawn is excluded in a subscript

If player leave the area with radius 80.0 80.0 or if the actor is dead,
the actor will be released from script and the reading process jumps back into 1.Loop


______________________________________________________________________________________
______________________________________________________________________________________
Additional Themes
Create a FXT file to show your own text message
Load a special actor
Tuning parts
Animations
Music, wave and sounds of Audio folder

Give access with math coding

______________________________________________________________________________________
______________________________________________________________________________________


Create a FXT file to show your own text message

Cleo makes possible to use a custom file to store text for using ingame
its called fake XT, according to the gxt file of the game
This requires to install the GxtHook.cleo in Cleo folder and an extra folder for the fxt files

Much users make it wrong, so again the explanation:
GxtHook.cleo must be placed in Cleo folder, not in a sub folder
Cleo_text folder must be a sub folder of Cleo folder
The fxt file must be placed in Cleo_text folder

GTASA game dir
- Cleo:GxtHook.cleo
- Cleo\Cleo_text: text.fxt

The fxt file will be read by game start.
If you have modified your fxt file it needs first to close the game complete
and then start again to apply the changes.

To create a fxt file needs to insert an entry name for the script and the real text to show, in a normal txt file
Then rename the file by chaning the extension from .txt into .fxt
Or create it directly with Sannybuilder and save it as .fxt , choose Any file (*.*) as extension

Entry name for the script and the real text to show must be done in this way:
<Entryname><space><text message>
only 1 space between Entryname and text message
Important:
only 1 space between words of the text message are allowed and NO space at the end
Maximum 7 symbols as entry name are allowed

Exemble:
Copy this line into a blanc page and save it as anyname.fxt

CODE
TXT_01 This is text of Cleo fxt file

Then use the script below to show the text by key_press

CODE
{$CLEO .cs}
:FXT
03A4: name_thread 'FXT'

:FXT_01
0001: wait 0 ms
if
0AB0:   key_pressed 84//--------- key = T
004D: jump_if_false @FXT_01
00BA: text_styled 'TXT_01'1000 ms1
0A93: end_custom_thread


The opcodes to show text are the same like to show text of american.gxt
There exist several opcodes to show text in different kinds. Look in opcode search tool.
Or look in Dutchys coding tut

If you wonna use entry names of american.gxt to use its text messages,
so look for a complete translation txt file in Sanny Install directory:
Sanny Builder 3\help\GXT Strings\GTASA.text


______________________________________________________________________________________
______________________________________________________________________________________



Load a special actor

There exist 2 kinds of actor models in the game.
One kind are models which are defined with a ID number in peds.ide and must be loaded with opcode 0247:

The other kind of actor models are not defined in peds.ide and must be loaded with opcode 023C:
These are called special actors and there are ID numbers reserved in peds.ide. From 290 up to 299
So 10 different special actors can be spawned at same time.

According to the theme Spawn a 3D model we need also 5 steps but with other opcodes

1. first step to load the special actor needs to insert the model name as short string

CODE
023C: load_special_actor 'ogloc' as 1

2. second step to prove if the model is loaded in an extra "load-model-check-Loop"

CODE
:Load_Model_Check
0001: wait0 ms
00D6: if0
023D:   special_actor1 loaded
004D: jump_if_false @Load_Model_Check

3. The model can be created as soon as the model file is loaded and define it with a variable name

CODE
009A: 0@ = create_actor_pedtype 24 model #SPECIAL01 at 2491.5-1667.513.35

4. release the loaded special actor model file if it not needed anymore

CODE
0296: unload_special_actor1

5. Release the defined item from script when the script has done its work
same like other actors

CODE
01C2: remove_references_to_actor 0@


The script below spawns a special actor by key_press at 4 virtual meters infront of the player
The script reads also the current interior to can spawn everywhere by using opcode 0860:
If the actor is dead he will be released from script und the reading process jumps back into 1.Loop

CODE
{$CLEO .cs}
:SPLACTOR_1
03A4: name_thread 'SPACTOR'

:SPACTOR_11
0001: wait 0 ms
00D6: if
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @SPACTOR_11
00D6: if
0AB0:   key_pressed 57//--------------------------------- key 9
004D: jump_if_false @SPACTOR_11
077E: get_active_interior_to 29@
023C: load_special_actor 'ogloc' as 1 // models 290-299

:SPACTOR_51
0001: wait 0 ms
00D6: if
823D:   not special_actor 1 loaded
004D: jump_if_false @SPACTOR_90
023C: load_special_actor 'OGLOC' as 1 // models 290-299
0002: jump @SPACTOR_51

:SPACTOR_90
04C4: store_coords_to 11@ 12@ 13@ from_actor $PLAYER_ACTOR with_offset 0.0 4.0 0.2
009A: 0@ = create_actor_pedtype 24 model #SPECIAL01 at 11@ 12@ 13@
0223: set_actor 0@ health_to 10000
0860: link_actor 0@ to_interior 29@
0296: unload_special_actor 1

:SPACTOR_158
0001: wait 0 ms
00D6: if
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @SPACTOR_201
00D6: if
8118:   not actor 0@ dead
004D: jump_if_false @SPACTOR_201
0002: jump @SPACTOR_158

:SPACTOR_201
01C2: remove_references_to_actor 0@ // Like turning an actor into a random pedestrian
0002: jump @SPACTOR_11



The opcode to create the actor is the same like for a normal ped.
Instead of inserting the peds model name will be used the entry #SPECIAL01
SPECIAL01 represent the ID 290 which the actor then get from the script
Its also possible to use the ID numbers instead of SPECIAL01

By creating more different special actors needs to give it then entries with numbers in ascending order
#SPECIAL01 and #SPECIAL02 or 290 and 291

The script below spawns 5 special actors
If one actor is dead all actors will be released from script und the reading process jumps back into 1.Loop
An advantage of special actors is to can add a new actor model with new model name without editing data files
Important: Maximum 7 symbols are allowed as model name


CODE
{$CLEO .cs}
:SPLACTOR_1
03A4: name_thread 'SPACMOR'

:SPACMOR_11
0001: wait 0 ms
00D6: if
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @SPACMOR_11
00D6: if
0AB0:   key_pressed 57//--------------------------------- key 9
004D: jump_if_false @SPACMOR_11
077E: get_active_interior_to 29@
023C: load_special_actor 'OGLOC' as 1 // models 290-299
023C: load_special_actor 'SMOKE' as 2 // models 290-299
023C: load_special_actor 'SWEET' as 3 // models 290-299
023C: load_special_actor 'RYDER2' as 4 // models 290-299
023C: load_special_actor 'CESAR' as 5 // models 290-299

:SPACMOR_116
0001: wait 0 ms
00D6: if or
823D:   not special_actor 1 loaded
823D:   not special_actor 2 loaded
823D:   not special_actor 3 loaded
823D:   not special_actor 4 loaded
823D:   not special_actor 5 loaded
004D: jump_if_false @SPACMOR_223
023C: load_special_actor 'OGLOC' as 1 // models 290-299
023C: load_special_actor 'SMOKE' as 2 // models 290-299
023C: load_special_actor 'SWEET' as 3 // models 290-299
023C: load_special_actor 'RYDER2' as 4 // models 290-299
023C: load_special_actor 'CESAR' as 5 // models 290-299
0002: jump @SPACMOR_116

:SPACMOR_223
04C4: store_coords_to 11@ 12@ 13@ from_actor $PLAYER_ACTOR with_offset -2.0 2.0 0.2
009A: 0@ = create_actor_pedtype 24 model #SPECIAL01 at 11@ 12@ 13@
0223: set_actor 0@ health_to 10000
0860: link_actor 0@ to_interior 29@
04C4: store_coords_to 11@ 12@ 13@ from_actor $PLAYER_ACTOR with_offset 0.0 2.0 0.2
009A: 1@ = create_actor_pedtype 24 model 291 at 11@ 12@ 13@
0223: set_actor 1@ health_to 10000
0860: link_actor 1@ to_interior 29@
04C4: store_coords_to 11@ 12@ 13@ from_actor $PLAYER_ACTOR with_offset 2.0 2.0 0.2
009A: 2@ = create_actor_pedtype 24 model #SPECIAL03 at 11@ 12@ 13@
0223: set_actor 2@ health_to 10000
0860: link_actor 2@ to_interior 29@
04C4: store_coords_to 11@ 12@ 13@ from_actor $PLAYER_ACTOR with_offset -2.0 4.0 0.2
009A: 3@ = create_actor_pedtype 24 model 293 at 11@ 12@ 13@
0223: set_actor 3@ health_to 10000
0860: link_actor 3@ to_interior 29@
04C4: store_coords_to 11@ 12@ 13@ from_actor $PLAYER_ACTOR with_offset 2.0 4.0 0.2
009A: 4@ = create_actor_pedtype 24 model #SPECIAL05 at 11@ 12@ 13@
0223: set_actor 4@ health_to 10000
0860: link_actor 4@ to_interior 29@
0296: unload_special_actor 1
0296: unload_special_actor 2
0296: unload_special_actor 3
0296: unload_special_actor 4
0296: unload_special_actor 5

:SPACMOR_563
0001: wait 0 ms
00D6: if
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @SPACMOR_626
00D6: if and
8118:   not actor 0@ dead
8118:   not actor 1@ dead
8118:   not actor 2@ dead
8118:   not actor 3@ dead
8118:   not actor 4@ dead
004D: jump_if_false @SPACMOR_626
0002: jump @SPACMOR_563

:SPACMOR_626
01C2: remove_references_to_actor 0@ // Like turning an actor into a random pedestrian
01C2: remove_references_to_actor 1@ // Like turning an actor into a random pedestrian
01C2: remove_references_to_actor 2@ // Like turning an actor into a random pedestrian
01C2: remove_references_to_actor 3@ // Like turning an actor into a random pedestrian
01C2: remove_references_to_actor 4@ // Like turning an actor into a random pedestrian
0002: jump @SPACMOR_11


______________________________________________________________________________________
______________________________________________________________________________________


Tuning parts

According to the theme Spawn a 3D model we need in this case only 4 steps and with other opcodes

1. first step to load the tuning part

CODE
06E9: request_car_component #hydralics
06E9: request_car_component #NTO_B_S
06E9: request_car_component 1115

2. second step to prove if the model is loaded in an extra "load-model-check-Loop"

CODE
:Load_Model_Check
0001: wait0 ms
ifand
06EA:   car_component_available #hydralics
06EA:   car_component_available #NTO_B_S
06EA:   car_component_available 1115
004D: jump_if_false @Load_Model_Check

3. The tuning part can be created as soon as the model file is loaded by attaching to the car

CODE
06E7: 1@ = add_car_component #NTO_B_S to_car 0@
06E7: 2@ = add_car_component #hydralics to_car 0@
06E7: 3@ = add_car_component 1115 to_car 0@

4. release the loaded tuning part model file if it is not needed anymore

CODE
06EB: release_car_component #hydralics
06EB: release_car_component #NTO_B_S
06EB: release_car_component 1115

To release the defined item from script is not nessesary


The script below spawns the car SLAMVAN with nitro, hydraulics and front bumper
and the paintjob 1 in Grovestreet if player goes into red marker
Adding paintjobs needs first to give the car white colors
Painjobs requires existing paintjob textures
These are additional txd files which have the same name like the dff model and its basic txd with an additional number
slamvan.dff and slamvan.txd as basic model files
slamvan1.txd as paintjob 0, slamvan2.txd as paintjob 1, etc...
If player leave the spot the car will be released from script and the reading process jumps back into 1.Loop

CODE
{$CLEO .cs}
:TuneP_1
03A4: name_thread 'TuneP'

:TuneP_2
0001: wait0 ms
00D6: if0
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @TuneP_2
00D6: if0
00FF:   actor $PLAYER_ACTOR1 (in-sphere)near_point_on_foot 2491.5-1667.513.35 radius1.01.01.0
004D: jump_if_false @TuneP_2

0247: request_model #SLAMVAN
06E9: request_car_component #hydralics
06E9: request_car_component #NTO_B_S
06E9: request_car_component 1115

:Load_Model_Check
0001: wait0 ms
ifand
0248:   model #SLAMVAN available
06EA:   car_component_available #hydralics
06EA:   car_component_available #NTO_B_S
06EA:   car_component_available 1115
004D: jump_if_false @Load_Model_Check

00A5: 0@ = create_car #SLAMVAN at 2487.5-1660.513.35
0175: set_car 0@ z_angle_to 180.0

06E7: 1@ = add_car_component #NTO_B_S to_car 0@
06E7: 2@ = add_car_component #hydralics to_car 0@
06E7: 3@ = add_car_component 1115 to_car 0@

0229: set_car 0@ color_to11
06ED: set_car 0@ paintjob1

06EB: release_car_component #hydralics
06EB: release_car_component #NTO_B_S
06EB: release_car_component 1115
0249: release_model #SLAMVAN

:TuneP_4
0001: wait0 ms
00D6: if0
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @TuneP_4
00D6: if0
80FF:   NOT   actor $PLAYER_ACTOR0 ()near_point_on_foot 2491.5-1667.513.35 radius2.02.02.0
004D: jump_if_false @TuneP_4
01C3: remove_references_to_car 0@// Like turning a car into any random car
0002: jump @TuneP_2



______________________________________________________________________________________
______________________________________________________________________________________



Animations

To use animations exist 2 opcodes, 0605: and 0812:

CODE
0605: actor $PLAYER_ACTOR perform_animation_sequence "TAI_CHI_IN" IFP_file "PARK" 4.0 loop 0 1 1 0 time -1
0812: AS_actor $PLAYER_ACTOR perform_animation "SWIM_BREAST" IFP_file "SWIM" 1.0 loopA 1 lockX 1 lockY 1 lockF 1 time -2


The animations are embeded in the IFP files

Important:

The IFP file ped.ifp is placed in GTASA\anim folder and all animations of ped.ifp are loaded by gamestart
It dont need to load the animation for the script. Never load the ifp file "ped" !!

The other IFP files are archived in gta3.img
It needs first to load the IFP file before using an animation of its file

The script below is an exemble to assign an animation of IFP file "ped" by key_press to player actor


CODE
{$CLEO .cs}
:IFP_PED
03A4: name_thread 'IFP_PED'

:IFP_PED_01
0001: wait 0 ms
if
0256: player $PLAYER_CHAR defined
004D: jump_if_false @IFP_PED_01
ifand
0AB0:   key_pressed 8//-----------------key = Backspace
80DF:   not actor $PLAYER_ACTOR driving
004D: jump_if_false @IFP_PED_01
0605: actor $PLAYER_ACTOR perform_animation_sequence "CAR_ROLLOUT_RHS" IFP_file "PED" 4.0 loop 0 1 1 0 time -1
0001: wait 2000 ms
0002: jump @IFP_PED_01


Several animations are defined as extra opcodes
Some exembles:
05C7: AS_actor $PLAYER_ACTOR use_atm
05C2: AS_actor $PLAYER_ACTOR show_the_finger
05C9: AS_actor $PLAYER_ACTOR on_guard 2000 ms
05C4: AS_actor $PLAYER_ACTOR hands_up 15000 ms
0729: AS_actor $PLAYER_ACTOR hold_cellphone 1// requires to load first the model #cellphone
0729: AS_actor $PLAYER_ACTOR hold_cellphone 0
05BC: AS_actor $PLAYER_ACTOR jump 1
05C3: AS_actor $PLAYER_ACTOR hands_cower
05C5: AS_actor $PLAYER_ACTOR cower 3000 ms




The other IFP files are archived in gta3.img and needs first to load the IFP file before using an animation of its file
According to the theme Spawn a 3D model we need also 5 steps but with other opcodes

1. first step to load the IFP file needs to insert the IFP file name as long string

CODE
04ED: load_animation "PARK"

2. second step to prove if the file is loaded in an extra "load-model-check-Loop"

CODE
:Load_Model_Check
0001: wait0 ms
00D6: if0
04EE:   animation "PARK" loaded
004D: jump_if_false @Load_Model_Check

3. The animation can now assigned to an actor as soon as the IFP file is loaded and the actor is available.
It requires to insert animation name and name of IFP file as long string

CODE
0812: AS_actor $PLAYER_ACTOR perform_animation "TAI_CHI_IN" IFP_file "PARK" 1.0 loopA 1 lockX 1 lockY 1 lockF 1 time -2

4. release the loaded IFP file if it is not needed anymore

CODE
04EF: release_animation "PARK"

5. Release a defined item is not possible but in some cases it needs to remove the animation from actor

CODE
0792: disembark_instantly_actor $PLAYER_ACTOR

In addition by using animation packs, it needs to release the pack

CODE
061B: remove_references_to_AS_pack 0@



The script below is an exemble to assign an animation of IFP file "PARK" by key_press to player actor
The animation will be repeated as long as the key is not pressed again, because of the value 1 in the parameter of loopA

CODE
{$CLEO .cs}
:IFP_PARK
03A4: name_thread 'IFPPARK'

:IFP_PARK_11
0001: wait 0 ms
00D6: if
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @IFP_PARK_11
00D6: if
0AB0:   key_pressed 8//-----------------key = Backspace
004D: jump_if_false @IFP_PARK_11
04ED: load_animation "PARK"

:IFP_PARK_54
0001: wait 0 ms
00D6: if
04EE:   animation "PARK" loaded
004D: jump_if_false @IFP_PARK_54

0812: AS_actor $PLAYER_ACTOR perform_animation "TAI_CHI_IN" IFP_file "PARK" 1.0 loopA 1 lockX 1 lockY 1 lockF 1 time -2 // versionB
0001: wait 1000 ms

:IFP_PARK_141
0001: wait 0 ms
00D6: if
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @IFP_PARK_141
00D6: if and
8AB0:   not key_pressed 8//-----------------key = Backspace
80E1:   not player 0 pressed_key 15
004D: jump_if_false @IFP_PARK_221
0002: jump @IFP_PARK_141

:IFP_PARK_221
0792: disembark_instantly_actor $PLAYER_ACTOR
04EF: release_animation "PARK"
0001: wait 1000 ms
0002: jump @IFP_PARK_11




Combine several animation to an AS_pack
The script below assigns sevaral animations of different IFP files combined in an AS_pack by key_press to player actor

CODE
{$CLEO .cs}
:AMPAK_00
03A4: name_thread 'APK'
0001: wait2000 ms

:AMPAK_1
0001: wait 50 ms
00D6: if
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @AMPAK_1
if
0AB0:   key_pressed 8//-----------------key = Backspace
004D: jump_if_false @AMPAK_1
04ED: load_animation "STRIP"
04ED: load_animation "DANCING"

:AMPAK_12
0001: wait0 ms
ifand
04EE:   animation "STRIP" loaded
04EE:   animation "DANCING" loaded
004D: jump_if_false @AMPAK_13
0002: jump @AMPAK_14

:AMPAK_13
04ED: load_animation "STRIP"
04ED: load_animation "DANCING"
0002: jump @AMPAK_12

:AMPAK_14
0615: define_AS_pack_begin 0@
0605: actor -1 perform_animation_sequence "STR_B2C" from_file "STRIP"4.00001 -1 ms
0605: actor -1 perform_animation_sequence "DNCE_M_A" from_file "DANCING"4.00001 -1 ms
0605: actor -1 perform_animation_sequence "STR_B2C" from_file "STRIP"4.00001 -1 ms
0605: actor -1 perform_animation_sequence "DNCE_M_A" from_file "DANCING"4.00001 -1 ms
0605: actor -1 perform_animation_sequence "STR_B2C" from_file "STRIP"4.00001 -1 ms
0605: actor -1 perform_animation_sequence "DAN_LOOP_A" from_file "DANCING"4.00001 -1 ms
0605: actor -1 perform_animation_sequence "DNCE_M_D" from_file "DANCING"4.00001 -1 ms
0643: set_AS_pack 0@ loop 1
0616: define_AS_pack_end 0@
0618: assign_actor $PLAYER_ACTOR to_AS_pack 0@
0001: wait 1000 ms

:AMPAK_21
0001: wait 0 ms
00D6: if
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @AMPAK_end
if
80E1:   not key_pressed015
004D: jump_if_false @AMPAK_end
ifor
0611:   actor $PLAYER_ACTOR animation == "STR_B2C"
0611:   actor $PLAYER_ACTOR animation == "DNCE_M_A"
0611:   actor $PLAYER_ACTOR animation == "STR_B2C"
0611:   actor $PLAYER_ACTOR animation == "DNCE_M_D"
004D: jump_if_false @AMPAK_end
0002: jump @AMPAK_21

:AMPAK_end
061B: remove_references_to_AS_pack 0@
04EF: release_animation "STRIP"
04EF: release_animation "DANCING"
0002: jump @AMPAK_1



Animation in air needs to move the actor with opcode 083C: and to use animation code 0812: with -2 as last parameter
Script below let the player swimming in air by key_press

CODE
{$CLEO .cs}
:Airswim
03A4: name_thread 'Airswim'

:AIRSWIM_11
0001: wait 0 ms
00D6: if
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @AIRSWIM_11
00D6: if
0AB0:   key_pressed 8//-----------------key = Backspace
004D: jump_if_false @AIRSWIM_11
04ED: load_animation "SWIM"

:AIRSWIM_54
0001: wait 0 ms
00D6: if
04EE:   animation "SWIM" loaded
004D: jump_if_false @AIRSWIM_54
083C: set_actor $PLAYER_ACTOR velocity_in_direction_XYZ 0.0 0.0 20.0
0001: wait 1000 ms
0812: AS_actor $PLAYER_ACTOR perform_animation "SWIM_BREAST" IFP_file "SWIM" 1.0 loopA 1 lockX 1 lockY 1 lockF 1 time -2 // versionB

:AIRSWIM_141
0001: wait 0 ms
00D6: if
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @AIRSWIM_141
083C: set_actor $PLAYER_ACTOR velocity_in_direction_XYZ 0.0 2.0 2.0
00D6: if and
8AB0:   not key_pressed 8
0611:   actor $PLAYER_ACTOR performing_animation "SWIM_BREAST"
004D: jump_if_false @AIRSWIM_221
0002: jump @AIRSWIM_141

:AIRSWIM_221
0792: disembark_instantly_actor $PLAYER_ACTOR
04EF: release_animation "SWIM"
0001: wait 1000 ms
0002: jump @AIRSWIM_11



How to find Animations:
use Ryosukes Animation Manager
The animations are stored in *.ifp files
One ifp file is the GTASA\anim\ped.ifp
(GTASA\anim\anim.img is unused)
The other ifp files are in gta3.img like colt45.ifp, python.ifp, rifle.ifp, tec.ifp, weapons.ifp
Import these and play these with Animation Manager
Deji provides a list of the animation names: List of animations in San Andreas

______________________________________________________________________________________
______________________________________________________________________________________


Music, wave and sounds of Audio folder

GTASA\AUDIO\Streams includes *.ogg files for music in vehicle, interiors, some missions and for cutscene
GTASA\AUDIO\SFX includes *.wav files for sounds and dialoge
look at GTA: SA SFX Directory

The Radio Music files can only be played in vehicles:
There is no chance for scripting to play them on foot
For radio exist only these codes to set radio station, to get radio staion number and to set to favourites station

CODE
041E: set_radio_station 3
051E: 1@ = get_current_radio_station
0A26: set_radio_to_favorite_station



Music of GTASA\AUDIO\Streams\BEAT and AMBIENCE can be played with other opcodes

CODE
0953: get_soundtrack_status_to 17@
if
0039:   17@ ==0;; integer values
004D: jump_if_false @
//
0952: load_soundtrack 12
//
0954: start_playing_loaded_soundtrack
//
0955: end_playing_loaded_soundtrack


//use following track numbers: 1, 2, 3, 4, 8, 9, 10, 12, 13



Play titel song

CODE
0394: play_music 1
//or
0394: play_music 2

its mostly used as flourish by mission comlete
find the song file in GTASA\AUDIO\Streams\BEAT



Sounds or speeches of GTASA\AUDIO\SFX are used for "wav"- or "sound"- playing
But the sounds of GENRL can not be played with scripting


A part of them are documented in data\AudioEvents.txt
These for the story dialoges and sounds for gameplay


///////SOUNDS/////
A small part of the listed sounds in AudioEvents can be startet with play sound opcodes: 018C: 097A: 09F1:
Find sounds in the range from SOUND_1002 to SOUND_1191. Not all worked by me. It seems that someone only can used from the exe
Someone of these sounds are durable and must be started with 018D: and stoped with 018E:

Some other ones of these sounds have a replay mode (music for minigames) and can be stoped with a stop sound
SOUND_PILOT_AWARD_TRACK_START 1187 start sound
SOUND_PILOT_AWARD_TRACK_STOP 1188 stop sound


///////WAVE/////
The most part of AudioEvents.txt includes waves and must used with

CODE
03CF: load_wav1828 as1
00D6: if0
03D0:   wav1 loaded
004D: jump_if_false @
03D1: play_wav 1

can be attached to actor or object

CODE
0949: link_wav 1 to_actor 0@

if wave is finish should be unloaded

CODE
040D: unload_wav 1

in original is usual to unload wav before loading a wav

CODE
:AUDIOL_33
00D6: if0
0039:   4@ ==0// integer values
004D: jump_if_false @AUDIOL_38
040D: unload_wav 3@
03CF: load_wav 7@ as 3@

you can also check if the sound is finish

CODE
00D6: if0
03D2:   wav 1 ended
004D: jump_if_false @



The sounds which are used with 03CF: load_wav 1828 as 1
are mostly dialog sounds of missions
The names of these waves, listed in AudioEvents.txt are the entry names from gxt dialog texts
exemble:
SOUND_MAN5_BK 24412
search in american.gxt for MAN5_BK
and find the dialog text:
~z~You got ice cold gangstas running through your veins!

The sound numbers have NO association with Audio file numbers, folder, banks
Only way I know to find sounds is to write a sound test script



///autom. phrases///////
Other way to let actor speak which is not written in AudioEvents.txt is

CODE
09D5: play_sound_of_actor $PLAYER_ACTOR soundslot 342 flags 111 as 2@


first param, $PLAYER_ACTOR is the actor variable name
second param (342) is a slot with some different phrases sounds
third, fourth, fift param of flags are unknown
last param, 2@ is variable name of this sound function, isnt need to release or deload it in any way
and cant used further more in any other opcode.

Note: the soundslots includes more sounds which are changed automaticly if the same soundslot runs again
The soundslot with same number includes different sounds for different actors

PLAYER_ACTOR, special actors, Females and males have different sounds
only with the special girlfriends actors (GANGRL2) is it possible to play the sex voices of GFSEX script
The shop sellers have own sounds and can not played with other actors

opcode 09D5 is the only way to play these voice sounds which are also mostly used from exe for random peds on street
like pain sounds, breathing, coughing ect...
presumable uses PAIN_A SFX, SPC_FA SFX, SPC_PA SFX Archive Directory,

look at GTA: SA SFX Directory


______________________________________________________________________________________
______________________________________________________________________________________




为主的祥助 发表于 2012-4-7 10:36:55

本帖最后由 kwanz 于 2012-4-18 18:05 编辑

数学运算编程
-用数学运算实现流程控制
-用局部变量实现流程控制
-声明还是不声明? (I)
-时间检测-真实毫秒数
-时间检测-游戏时间
-整型数和浮点数
-声明还是不声明? (II)
-整型与浮点型的转换
-用text_draw opcode显示数学运算的值
-运算编程
______________________________________________________________________________________
______________________________________________________________________________________
用数学运算实现流程控制
运算编程不只是用来计算。
写运算程序的一个重要作用是控制脚本程序的执行段落
为此我们声明一个变量
//example:
$RYDER_TOTAL_PASSED_MISSIONS = 0
0@ = 0
接下来我们检查这个变量是否等于某个值,若相等,则想判定的条件成立
两个最重要的流程控制检查,是原版main.scm中的任务启动代码和ONMISSION标志是否为零的检测
$ONMISSION声明在原版main.scm的MAIN分节,作为一个特殊的任务状态控制器
set_on_mission_flag_to $ONMISSION
ONMISSION在新游戏开始时的第一次更改,是自由城机场的开场任务
:INTRO_47
$ONMISSION = 1
下面的代码是任务RYDER的启动部分的缩减版
检测$ON_MISSION==0且$RYDER_TOTAL_PASSED_MISSIONS==0
若条件成立,则跳到RYDER任务开始处
但它首先把$ONMISSION设为1,防止其他任务从启动代码处启动
$RYDER_TOTAL_PASSED_MISSIONS的值在R点任务完成的时候改变
注意,在CLEO中使用全局变量,可能会导致bug或死机,只有%PLAYER_CHAR, $PLAYER_ACTOR, $ONMISSION可以放心使用
:RYDER_11
wait 0
if
Player.Defined($PLAYER_CHAR)
else_jump @RYDER_342
if
$ONMISSION == 0
else_jump @RYDER_342
if
00FF: actor $PLAYER_ACTOR sphere 0 in_sphere $X_RYDER_HOUSE $Y_RYDER_HOUSE $Z_RYDER_HOUSE radius 1.6 1.2 2.0 on_foot
else_jump @RYDER_342
if
$RYDER_TOTAL_PASSED_MISSIONS == 0
else_jump @RYDER_238
$ONMISSION = 1
start_mission 24 // Home Invasion
jump @RYDER_238

:RYDER_238
if
$RYDER_TOTAL_PASSED_MISSIONS == 1
else_jump @RYDER_290
$ONMISSION = 1
start_mission 25 // Catalyst

:RYDER_290
if
$RYDER_TOTAL_PASSED_MISSIONS == 2
else_jump @RYDER_342
$ONMISSION = 1
start_mission 26 // Robbing Uncle Sam

:RYDER_342
jump @RYDER_11
$RYDER_TOTAL_PASSED_MISSIONS的值在R点任务完成的时候改变 它会自加1
$RYDER_TOTAL_PASSED_MISSIONS += 1
第一个任务结束后它就等于1
$RYDER_TOTAL_PASSED_MISSIONS = 1
然后再检查是否有$RYDER_TOTAL_PASSED_MISSIONS==1成立,若是则开始下一个任务
if
$RYDER_TOTAL_PASSED_MISSIONS == 1
else_jump @RYDER_290
$ONMISSION = 1
start_mission 25 // Catalyst 催化剂

用局部变量实现流程控制

用单等号赋值
1@ = 0

用双等号判断两个值是否相等
1@ == 0

下面的代码去除进出老家的倒三角,并在人物5@被杀死后还原
检查标志变量1@分为3步
我们这里只需要一个循环来执行多条指令
当然还有一个检测模型加载的循环不在讨论范围内

首先,程序检查玩家是否在0号空间,也就是室外空间,以防玩家被困在屋内
077E: get_active_interior_to 29@ 声明了变量29@并赋值
如果玩家在室外,进入室内标志被移除,标志变量被改写
1@ = 1
然后程序执行第二步检查,检查玩家是否进圈,继续执行程序
if
0039: 1@ == 1
if
00FF: actor $PLAYER_ACTOR 1 (in-sphere)near_point_on_foot 2491.5 -1667.5 13.35 radius 1.0 1.0 1.0

如果两个条件同时满足,则刷出人物5@,跟玩家打架
若人物5@被杀死,则再次改写标志变量,继续执行第三步程序
也就是,若人物5@被杀死,则老家恢复可进入,程序结束

若玩家不攻击5@而逃跑,则返回第二步判断
检测5@和玩家的距离是否大于80.0
若是,则解除对人物5@的引用,1@被赋为1
{$CLEO .cs}
:Access_1
03A4: name_thread 'Access_'
1@ = 0

:Access_2
0001: wait 0 ms
00D6: if 0
0256: player $PLAYER_CHAR defined
004D: jump_if_false @Access_2

if//-- 第一步检测
0039: 1@ == 0
004D: jump_if_false @Access_3//------ 跳到下一步
077E: get_active_interior_to 29@
if
0039: 29@ == 0
004D: jump_if_false @Access_2
07FB: set_interior 'CARLS' access 0
1@ = 1//--- 记录开启第二步判断

:Access_3//-- 第二步判断
if
0039: 1@ == 1
004D: jump_if_false @Access_7//------ 跳到下一步
if
00FF: actor $PLAYER_ACTOR 1 (in-sphere)near_point_on_foot 2491.5 -1667.5 13.35 radius 1.0 1.0 1.0
004D: jump_if_false @Access_2
0247: request_model #TRIBOSS
0247: request_model #AK47

:Access_4//-- 加载模型循环
0001: wait 0 ms
00D6: if and
0248: model #TRIBOSS available
0248: model #AK47 available
004D: jump_if_false @Access_4//--加载模型循环
009A: 5@ = create_actor 24 #TRIBOSS at 2486.5 -1664.5 13.45
01B2: give_actor 5@ weapon 30 ammo 99999
05E2: AS_actor 5@ kill_actor $PLAYER_ACTOR
0249: release_model #TRIBOSS
1@ = 2//--- 记录开启第三步判断

:Access_7//-- 第三步判断
if
0039: 1@ == 2
004D: jump_if_false @Access_2//------ 返回上层判断
00D6: if 0
0118: actor 5@ dead
004D: jump_if_false @Access_9
01C2: remove_references_to_actor 5@
07FB: set_interior 'CARLS' access 1
0A93: end_custom_thread

:Access_9
00D6: if 0
8104: NOT actor $PLAYER_ACTOR near_actor 5@ radius 80.0 80.0 10.0 sphere 0
004D: jump_if_false @Access_2
009B: destroy_actor 5@
1@ = 1//--- 返回第二层判断
0002: jump @Access_2
______________________________________________________________________________________
______________________________________________________________________________________
声明还是不声明? (I)

声明变量有时是不必要的
未声明的变量会自动被设为0

这跟变量的引用位置和作用密切相关
我建议在用变量做流程控制的时候都预先声明
这样能使程序更稳定,因为声明避免了多线程访问时交叉引用和计算赋值引起的bug

有一种不用声明的情况是变量从脚本执行开始前已经存在
一个说明这种情况的例子是“随处存车”
请参阅主题:Special Particularities in Cleo
- Script Exemble by using Special Global Cleo Variable/ Store a car at any place

程序的开头部分是这样的
{$CLEO .cs}
:CARSTORE
03A4: name_thread 'CARSTOR'
0001: wait 1000 ms
0AB4: 7@ = var 955
00D6: if
8039: not 7@ == 0
004D: jump_if_false @CARSTOR_150

如果存车程序从新游戏或者载入存档时开始运行
它首先检查var 955是否为0
它尽当车子已经存在载入的存档里时不为0
若955为0,则开始循环1
若955不为0,程序跳到循环3,检查玩家是否在车子的保存位置

另外一个例子是检查一段程序是从CLEO中加载的,还是用create_custom_thread中创建的线程
0A92: create_custom_thread "ThreadStartTest.cs"
请参阅主题: Special Particularities in Cleo >> create_custom_thread

.CS脚本默认从CLEO主程序直接加载执行
若某脚本程序只能从另一个线程中用create_custom_thread启动,可以通过检查某个未声明变量的方法,跳过 CLEO程序的初始化部分

未声明变量默认设为0,尤其是它从CLEO程序启动的时候
现在我们可以用带参的create_custom_thread声明另一个线程中的局部变量
0A92: create_custom_thread "ThreadStartTest.cs" 1
启动线程按以下规则得到参数的值
0@ <---- 参数1

下面的程序必须被保存为ThreadStartTest.txt,并编译为ThreadStartTest.cs,因为另外的程序已经指定了create_thread命令的入口
0A92: create_custom_thread "ThreadStartTest.cs" 1

若程序从CLEO主程序启动,0@默认被设为0
然后继续执行end_custom_thread语句终止线程

若它从另一个线程中用以上的create_thread命令启动
0@经传递获得数值1
程序经检测后跳入循环,启动热敏夜视仪
{$CLEO .cs}
:ThreadStartTest
if
0039: 0@ == 0
004D: jump_if_false @ThreadStartTest_1
0A93: end_custom_thread

:ThreadStartTest_1
03A4: name_thread "THREADST"

:ThreadStartTest_2
0001: wait 0 ms
if
0256: player $PLAYER_CHAR defined
004D: jump_if_false @ThreadStartTest_2
if
0AB0: key_pressed 8//-----------------按退格
004D: jump_if_false @ThreadStartTest_2
08B2: toggle_thermal_vision 1
0001: wait 3000 ms
08B2: toggle_thermal_vision 0
0002: jump @ThreadStartTest_2
稍微改变流程控制检测的写法并使用带参的create_custom_thread可以在单个cs文件中写多个线程,并让它们同时执行
带参的create_custom_thread可以启动调用命令的同一段程序(递归调用)
______________________________________________________________________________________
______________________________________________________________________________________
时间检测-真实毫秒数

局部变量32@和33@是预留作时间检测用的,它们的数值是以毫秒为单位递增的,并且总是整型
我们可以把变量置零来重置计数器
33@ = 0
赋值以后它从新值开始继续增加
利用它可以判断是否已过一段时间
if
33@ > 5000
下面的代码不断检查是否已过5秒
若是,则显示一条消息并清零计数器
{$CLEO .cs}
:Timecheck_1
thread "TIME"
33@ = 0

:Timecheck_2
wait 0 ms
if
33@ > 5000
jf @Timecheck_2
00BA: text_styled 'FEM_OK' 1000 ms 1
33@ = 0
jump @Timecheck_2
重要提示 若调慢游戏时间,则实时计时器也随之变慢
______________________________________________________________________________________
______________________________________________________________________________________
时间检测-游戏时间
Opcode 00BG返回游戏时间的小时和分钟数值
00BF: 0@ = current_time_hours, 1@ = current_time_minutes

可用关系算符如>或>=来检测经过的游戏时间
下面的代码在22点和2点之间启动热敏夜视仪
变量3@的作用是防止opcode 08B2被无限执行
时间判断语句获得使用夜视仪的时间
无论你是一读档就是半夜,还是游戏进行到开启时间,效果都是一样的
{$CLEO .cs}
:GameTime_1
thread "GTIME"
3@ = 0

:GameTime_2
wait 0
00BF: 0@ = current_time_hours, 1@ = current_time_minutes
if or
0@ >= 22
2 > 0@
jf @GameTime_3
if
3@ == 0
jf @GameTime_3
08B2: enable_thermal_vision 1
3@ = 1

:GameTime_3
if and
0@ > 1
22 > 0@
3@ == 1
jf @GameTime_2
08B2: enable_thermal_vision 0
3@ = 0
jump @GameTime_2
______________________________________________________________________________________
______________________________________________________________________________________
整型数和浮点数
以上的讲解都还只用到整型数
但有些情况还是要用到浮点数的,比如坐标检测和计算
下面的代码把玩家传送到500.0单位高的空中
玩家会一直下落,在离地面很近的时候,又被送到天上
首先,程序检查确保玩家在室外空间
然后,程序不断读取玩家离地面的高度
这里用到了浮点大小比较opcode来控制put_actor语句的执行
if
0023: 25.0 > 3@

{$CLEO .cs}
:Floatcheck_1
03A4: name_thread "FLOAT"

:Floatcheck_2
0001: wait 0 ms
if
0256: player $PLAYER_CHAR defined
004D: jump_if_false @Floatcheck_2
077E: get_active_interior_to 29@
if
0039: 29@ == 0
004D: jump_if_false @Floatcheck_2
0819: 3@ = actor $PLAYER_ACTOR distance_from_ground
if
0023: 25.0 > 3@
004D: jump_if_false @Floatcheck_2
00A1: put_actor $PLAYER_ACTOR at 0.0 0.0 500.0
0002: jump @Floatcheck_2
______________________________________________________________________________________
______________________________________________________________________________________
声明还是不声明? (II)
在需要浮点数的地方,游戏不能处理整型数,反之亦然
另外,对整型数和浮点数的数值运算有两套不同的opcode

还好,SB很智能,知道什么时候要用整型,什么时候要用浮点,调正确的函数的工作在编译的时候就完成了
试试编译上面的程序,然后反编译生成的cs,并勾上选项without opcodes
然后你会得到这样的代码
{$CLEO .cs}

//-------------MAIN---------------
thread "FLOAT"

:FLOAT_9
wait 0
if
Player.Defined($PLAYER_CHAR)
jf @FLOAT_9
077E: get_active_interior_to 29@
if
29@ == 0
jf @FLOAT_9
0819: 3@ = actor $PLAYER_ACTOR distance_from_ground
if
25.0 > 3@
jf @FLOAT_9
Actor.PutAt($PLAYER_ACTOR, 0.0, 0.0, 500.0)
jump @FLOAT_9


The most opcodes are disappeared
Sanny knows that floats are meant in this function:
25.0 > 3@

但是有几处函数是不明确的,比如计算两个变量
21@ -= 2@
要指明用到的是整型数还是浮点,一种方法是写出带opcode的函数
0063: 21@ -= 2@ // (float)
另一种方法是在赋初值的时候,声明变量是浮点数还是整数
如整型变量
21@ = 0
2@ = 0
或浮点
21@ = 0.0
2@ = 0.0
相关请参阅SB帮助:Coding >> Variables, Coding >> Constants
______________________________________________________________________________________
______________________________________________________________________________________
整型与浮点型的转换
Opcode 0092: 浮点数转换为整数
0092: 3@ = float 2@ to_integer
2@ 为浮点数 3@为整数 小数部分截去

Opcode 0093: 整数转换为浮点数
0093: 9@ = integer 8@ to_float
8@ 为整数 9@为浮点数,在8@后加.0
______________________________________________________________________________________
______________________________________________________________________________________
用text_draw opcode显示数学运算的值
显示数值可以帮助查找错误,调试程序
03F0: enable_text_draw 1
045A: text_draw_1number 250.0 40.0 'NUMBER' 3@
opcode 045A: 显示指定变量的值
但只能显示整型数
要显示浮点数,必须先用0092转换
opcode 045A需要写在循环里,并且循环外调用opcode 03F0
opcode 045A是text_draw类函数的一个,用于显示GTASA\models\txd存储的字体
先设03F0为1,再循环调用text_draw语句是一种常用的做法,比如在赛车中显示时间和排名,还有CLEO速度表

text_draw类opcode有一个缺点,就是会影响其他text类opcode的消息显示
反之,若有另外的text opcode调用,这条文本就显示不出来了

如果不用循环的话,有一个小技巧
03F0: text_draw_toggle 1
0001: wait 50 ms
03F0: text_draw_toggle 0
0001: wait 50 ms
045A: text_draw_1number 250.0 40.0 'NUMBER' 3@
这样消息就会一直显示,直到03F0再次被调用

下面的程序是前面的时间检测和浮点检测的综合
它显示实时计数器33@的值(上),空间编号(中),离地距离(下)
如果你在读档后进入建筑内部,离地距离不会显示,但是你能看到室内空间编号
当你出到室外以后,就会被瞬移到天上,然后就可以看到离地距离
实时计数器会每隔50秒刷新,并显示消息OK
调00BA显示的消息会中断text_draw显示
{$CLEO .cs}
:ValueCheck_1
03A4: name_thread "VCHECK"
33@ = 0

:ValueCheck_2
0001: wait 0 ms
if
0256: player $PLAYER_CHAR defined
004D: jump_if_false @ValueCheck_2
077E: get_active_interior_to 29@
03F0: enable_text_draw 1
045A: text_draw_1number 250.0 40.0 'NUMBER' 33@
045A: text_draw_1number 250.0 50.0 'NUMBER' 29@
if
0039: 29@ == 0
004D: jump_if_false @ValueCheck_3
0819: 3@ = actor $PLAYER_ACTOR distance_from_ground
0092: 4@ = float 3@ to_integer
03F0: enable_text_draw 1
045A: text_draw_1number 250.0 60.0 'NUMBER' 4@
if
0023: 25.0 > 3@
004D: jump_if_false @ValueCheck_3
00A1: put_actor $PLAYER_ACTOR at 0.0 0.0 500.0

:ValueCheck_3
if
33@ > 50000
jf @ValueCheck_2
00BA: text_styled 'FEM_OK' 1000 ms 1
33@ = 0
jump @ValueCheck_2
______________________________________________________________________________________
______________________________________________________________________________________
运算编程
可以使用以下基本的整型和浮点操作
自加: +=
自减: -=
自除: /=
自乘: *=
赋值: =

计算圆上定角的坐标可以用正弦和余弦函数,必须用浮点
02F7: 13@ = sine 45.0 // (float)
02F6: 14@ = cosine 45.0 // (float)

另外可以用以下的判断
大于: >
大于等于: >=
判等: ==

其他命令可以查阅SB帮助: Coding >> Additional commands

下面的代码当按退格时在玩家周围生成烟雾
按住退格键显示一圈烟雾
4@用作角度,求余弦得x坐标,求正弦得y坐标,然后乘4.0,得到以玩家为心以4为半径的圆
把数值传入04C4 绕玩家的相对坐标
然后每次递增5度,计算下一个烟雾生成点的位置
{$CLEO .cs}
:Sine_1
03A4: name_thread 'SINE'
0007: 4@ = 0.0 // floating-point values

:Sine_2
0001: wait 0 ms
00D6: if 0
0256: player $PLAYER_CHAR defined
004D: jump_if_false @Sine_2
if
0AB0: key_pressed 8//------Backspace
004D: jump_if_false @Sine_2
02F6: 5@ = cosine 4@ // sinus swapped with cosine
0013: 5@ *= 4.0 // floating-point values (never used in VC or GTA 3)
02F7: 6@ = sinus 4@ // cosine swapped with sinus
0013: 6@ *= 4.0 // floating-point values (never used in VC or GTA 3)
04C4: create_coordinate 1@ 2@ 3@ from_actor $PLAYER_ACTOR offset 5@ 6@ 0.2
095C: create_smoke_at 1@ 2@ 3@ velocity 0.0 0.0 0.0 RGBA 1.0 1.0 1.0 1.0 size 0.2 last_factor 0.1
000B: 4@ += 5.0
if
0021: 4@ > 354.0 // floating-point values
004D: jump_if_false @Sine_2
0007: 4@ = 0.0
jump @Sine_2

最后这个程序显示玩家的当前坐标
含分割符逗号,但无小数点,请自行YY
{$CLEO .cs}
:coords_00
03A4: name_thread 'COO'
0006: 33@ = 0 // integer values
0006: 3@ = 0 // integer values
0006: 4@ = 0 // integer values
0006: 5@ = 0 // integer values
0006: 11@ = 0 // integer values
0006: 12@ = 0 // integer values
0006: 13@ = 0 // integer values
0006: 9@ = 0 // integer values

:coords_01
0001: wait 0 ms
00D6: if 0
0256: player $PLAYER_CHAR defined
004D: jump_if_false @coords_01
03F0: enable_text_draw 1
045A: text_draw_1number 50.0 425.0 'NUMBER' 3@ // value
045A: text_draw_1number 200.0 425.0 'NUMBER' 4@ // value
045A: text_draw_1number 350.0 425.0 'NUMBER' 5@ // value
045A: text_draw_1number 100.0 425.0 'NUMBER' 11@ // value
045A: text_draw_1number 250.0 425.0 'NUMBER' 12@ // value
045A: text_draw_1number 400.0 425.0 'NUMBER' 13@ // value
045A: text_draw_1number 450.0 425.0 'NUMBER' 9@ // value
if
0019: 33@ > 1000 // integer values
004D: jump_if_false @coords_01
0006: 33@ = 0 // integer values
00A0: store actor $PLAYER_ACTOR position to 0@ 1@ 2@
0092: 3@ = float_to_integer 0@
0092: 4@ = float_to_integer 1@
0092: 5@ = float_to_integer 2@

0093: 6@ = integer_to_float 3@
0093: 7@ = integer_to_float 4@
0093: 8@ = integer_to_float 5@

0063: 0@ -= 6@ // floating-point values
0063: 1@ -= 7@ // floating-point values
0063: 2@ -= 8@ // floating-point values
0013: 0@ *= 100.0 // floating-point values
0013: 1@ *= 100.0 // floating-point values
0013: 2@ *= 100.0 // floating-point values

0092: 11@ = float_to_integer 0@
0092: 12@ = float_to_integer 1@
0092: 13@ = float_to_integer 2@

:coords_02
00D6: if 0
001B: 0 > 11@ // integer values
004D: jump_if_false @coords_03
0012: 11@ *= -1 // integer values

:coords_03
00D6: if 0
001B: 0 > 12@ // integer values
004D: jump_if_false @coords_04
0012: 12@ *= -1 // integer values

:coords_04
00D6: if 0
001B: 0 > 13@ // integer values
004D: jump_if_false @coords_05
0012: 13@ *= -1 // integer values

:coords_05
0172: 9@ = actor $PLAYER_ACTOR z_angle
0092: 9@ = float_to_integer 9@
0002: jump @coords_01
______________________________________________________________________________________
______________________________________________________________________________________

为主的祥助 发表于 2012-4-7 10:37:35

本帖最后由 kwanz 于 2012-4-18 18:10 编辑

数组

总的来讲,数组的原理是很简单的,不过运用到数组的各种程序很容易造成疑惑。另外,数组的构造也比较纠结。

简单地说,我们可以为一个变量赋予更多内容,这个变量就像一个有孩子的家庭,家庭的索引定义了每一部分的含义。

Family = father
Family = mother
Family = son
Family = doughter
Family = Carl

Family进了厨房
意思就是母亲进了厨房

我们用GTA和局部变量的术语来解释,我们用同一个变量名来维护数组结构,但我们必须预留更多的局部变量

6@ = father
6@ = mother
6@ = son
6@ = doughter
6@ = Carl

指定递增的索引数,实际上需要占用升序的后续局部变量的空间
6@ = father
7@ = mother
8@ = son
9@ = doughter
10@ = Carl

数组结构里最重要的访问入口就是索引
数组的结构是这样的
6@(30@,5i)

30@是数组索引
我们现在定义索引的值为
0006: 30@ = 4

那么
6@(30@,5i)进了厨房
意思就是Carl进了厨房
它等同于
10@进了厨房

一些实际程序的例子:
下面的4段程序都在Grove St生成5样相同的物品

模型ID, 名称
1239, info
1240, health
1241, adrenaline
1242, bodyarmour
1247, bribe

每一段代码都做了一点修改
我们一点点地做,首先看执行几个简单的生成命令的版本

1. 简单版{$CLEO .cs}
:more_items1
03A4: name_thread 'm_item1'

//1239, info
//1240, health
//1241, adrenaline
//1242, bodyarmour
//1247, bribe

0213: 0@ = create_pickup 1239 type 15 at 2490.0 -1662.0 13.5
0213: 1@ = create_pickup 1240 type 15 at 2492.0 -1662.0 13.5
0213: 2@ = create_pickup 1241 type 15 at 2494.0 -1662.0 13.5
0213: 3@ = create_pickup 1242 type 15 at 2496.0 -1662.0 13.5
0213: 4@ = create_pickup 1247 type 15 at 2498.0 -1662.0 13.5

0A93: end_custom_thread2. 然后我们用局部变量来定义物品ID{$CLEO .cs}
:more_items2
03A4: name_thread 'm_item2'

0006: 6@ = 1239 // info
0006: 7@ = 1240 // health
0006: 8@ = 1241 // adrenaline
0006: 9@ = 1242 // bodyarmour
0006: 10@ = 1247 //bribe

0213: 0@ = create_pickup 6@ type 15 at 2490.0 -1662.0 13.5
0213: 1@ = create_pickup 7@ type 15 at 2492.0 -1662.0 13.5
0213: 2@ = create_pickup 8@ type 15 at 2494.0 -1662.0 13.5
0213: 3@ = create_pickup 9@ type 15 at 2496.0 -1662.0 13.5
0213: 4@ = create_pickup 10@ type 15 at 2498.0 -1662.0 13.5

0A93: end_custom_thread3. 现在我们用数组来定义物品 ID
30@为数组索引
每刷出一个物品,就把索引增加1
000A: 30@ += 1{$CLEO .cs}
:Array_items1
03A4: name_thread 'Array_1'

0006: 6@ = 1239 // info
0006: 7@ = 1240 // health
0006: 8@ = 1241 // adrenaline
0006: 9@ = 1242 // bodyarmour
0006: 10@ = 1247 //bribe

0006: 30@ = 0 // ---Array Index is 0
0213: 0@ = create_pickup 6@(30@,5i) type 15 at 2490.0 -1662.0 13.5

000A: 30@ += 1// ---Array Index is 1
0213: 1@ = create_pickup 6@(30@,5i) type 15 at 2492.0 -1662.0 13.5

000A: 30@ += 1// ---Array Index is 2
0213: 2@ = create_pickup 6@(30@,5i) type 15 at 2494.0 -1662.0 13.5

000A: 30@ += 1// ---Array Index is 3
0213: 3@ = create_pickup 6@(30@,5i) type 15 at 2496.0 -1662.0 13.5

000A: 30@ += 1// ---Array Index is 4
0213: 4@ = create_pickup 6@(30@,5i) type 15 at 2498.0 -1662.0 13.5

0A93: end_custom_thread4. 我们把生成5个物品的命令缩为一句,这句命令要执行5次
每次程序跳回生成命令前,数组索引自加1,以读取一个新的物品ID
为了确保命令被执行5遍,需要判断索引是否小于等于5
if
001B: 5 > 30@

并且我们不能把5个东西刷出在同一个位置上
我们需要修改坐标参数,也就是把x坐标用数组储存
因此我们首先定义存放坐标的变量{$CLEO .cs}
:Array_items2
03A4: name_thread 'Array_2'

0006: 6@ = 1239 // info
0006: 7@ = 1240 // health
0006: 8@ = 1241 // adrenaline
0006: 9@ = 1242 // bodyarmour
0006: 10@ = 1247 //bribe

0007: 11@ = 2490.0
0007: 12@ = 2492.0
0007: 13@ = 2494.0
0007: 14@ = 2496.0
0007: 15@ = 2498.0

0006: 30@ = 0 // ---数组索引


:Array_items2_loop
0001: wait 0 ms
if
001B: 5 > 30@
004D: jump_if_false @Array_items2_end
0213: 0@(30@,5i) = create_pickup 6@(30@,5i) type 15 at 11@(30@,5f) -1662.0 13.5
000A: 30@ += 1
0002: jump @Array_items2_loop

:Array_items2_end
0A93: end_custom_thread---------------------------------------------------------------------------------------------------------------------------------------
最后我们给出数组的完整描述方式:
6@(30@,5i)
<家族变量名>(<索引变量>,<最大存放量><成员类型:i表示整型,f表示浮点,s表示字符串>)

最大存放量的意思是,上面的例子里,最大的变量数为5
所以我们只能用数组创建5个物体
如果我们写成6@(30@,2i)我们只能创建2个物体
不过我们可以写6@(30@,12i),但只创建5个物体
如果我们需要创建20个物体,我们需要增加最大值:6@(30@,20i)
但是在Cleo CS脚本里是不可能创建20个物体的
因为我们需要20个局部变量来定义物体,20个局部变量来存储不同的坐标
而cs正常线程只支持32个局部变量
---------------------------------------------------------------------------------------------------------------------------------------
另外一种数组的表示方法看起来更清晰一点
只写上数组明和方括号括起的索引:0@
这种表达需要一开始就定义好数组
var
0@: array 5 of Integer
end

下面是不带opcode的程序。按上面的格式修改编译后,数组的结构会发生改变{$CLEO .cs}
thread 'ARRAY_2'

var
0@: array 5 of Integer
6@: array 5 of Integer
11@: array 5 of Float
end

6@ = 1239
7@ = 1240
8@ = 1241
9@ = 1242
10@ = 1247
11@ = 2490.0
12@ = 2492.0
13@ = 2494.0
14@ = 2496.0
15@ = 2498.0
30@ = 0

:ARRAY_1
wait 0
if
5 > 30@
jf @ARRAY_3
0@ = Pickup.Create(6@, 15, 11@, -1662.0, 13.5)
30@ += 1
jump @ARRAY_1

:ARRAY_3
0A93: end_custom_thread---------------------------------------------------------------------------------------------------------------------------------------
下面的代码演示了如何在程序中进一步利用数组定义的物品
下面两种使用普通局部变量的做法和访问一族变量的子成员是一样的:
if
0214: pickup 2@ picked_up

一是使用数组结构,并用数值指定索引
0006: 30@ = 1 // ---数组索引
0164: disable_marker 16@(30@,5i)

二是在循环过程中还原索引和物品标记
or to restore the index and assigne markers to the pickups in an array loop:
:Array_items3_restore
0006: 30@ = 0 // ---还原数组索引

:Array_items3_marker
0001: wait 0 ms
if
001B: 5 > 30@
004D: jump_if_false @Array_items3_check1
03DC: 16@(30@,5i) = create_marker_above_pickup 0@(30@,5i)
000A: 30@ += 1
0002: jump @Array_items3_marker{$CLEO .cs}
:Array_items3
03A4: name_thread 'Array_3'

0006: 6@ = 1239 // info
0006: 7@ = 1240 // health
0006: 8@ = 1241 // adrenaline
0006: 9@ = 1242 // bodyarmour
0006: 10@ = 1247 //bribe

0007: 11@ = 2490.0
0007: 12@ = 2492.0
0007: 13@ = 2494.0
0007: 14@ = 2496.0
0007: 15@ = 2498.0

0006: 30@ = 0 // ---数组索引


:Array_items3_create
0001: wait 0 ms
if
001B: 5 > 30@
004D: jump_if_false @Array_items3_restore
0213: 0@(30@,5i) = create_pickup 6@(30@,5i) type 3 at 11@(30@,5f) -1662.0 13.5
000A: 30@ += 1
0002: jump @Array_items3_create

:Array_items3_restore
0006: 30@ = 0 // ---还原索引

:Array_items3_marker
0001: wait 0 ms
if
001B: 5 > 30@
004D: jump_if_false @Array_items3_check1
03DC: 16@(30@,5i) = create_marker_above_pickup 0@(30@,5i)
000A: 30@ += 1
0002: jump @Array_items3_marker

:Array_items3_check1
0001: wait 0 ms
if
0256: player $PLAYER_CHAR defined
004D: jump_if_false @Array_items3_check1
if
0214: pickup 0@ picked_up
004D: jump_if_false @Array_items3_check2
0006: 30@ = 0 // ---数组索引
0164: disable_marker 16@(30@,5i)

:Array_items3_check2
if
0214: pickup 1@ picked_up
004D: jump_if_false @Array_items3_check3
0006: 30@ = 1 // ---数组索引
0164: disable_marker 16@(30@,5i)

:Array_items3_check3
if
0214: pickup 2@ picked_up
004D: jump_if_false @Array_items3_check4
0006: 30@ = 2 // --数组索引
0164: disable_marker 16@(30@,5i)

:Array_items3_check4
if
0214: pickup 3@ picked_up
004D: jump_if_false @Array_items3_check5
0006: 30@ = 3 // ---数组索引
0164: disable_marker 16@(30@,5i)

:Array_items3_check5
if
0214: pickup 4@ picked_up
004D: jump_if_false @Array_items3_check6
0006: 30@ = 4 // ---数组索引
0164: disable_marker 16@(30@,5i)

:Array_items3_check6
if or
075C: marker 16@ enabled
075C: marker 17@ enabled
075C: marker 18@ enabled
075C: marker 19@ enabled
075C: marker 20@ enabled
004D: jump_if_false @Array_items3_Endrestore
0002: jump @Array_items3_check1

:Array_items3_Endrestore
0006: 30@ = 0 // ---数组索引
0002: jump @Array_items3_create下面的程序十分有用,它生成10个带箭头标号的人物,并且去除被杀死的人物的箭头,另用一个局部变量记录被杀死的人数
走到室外并按9触发刷人程序{$CLEO .cs}
:ArrayAct_1
03A4: name_thread 'ARRAY_A'
0006: 28@ = 0 // 杀死数计数器
0006: 30@ = 0 // 数组索引
0007: 31@ = 2.5 // 刷人坐标的y偏移量

:ArrayAct_2
0001: wait 0 ms
00D6: if 0
0256: player $PLAYER_CHAR defined
004D: jump_if_false @ArrayAct_2
if and
0AB0: key_pressed 57//----------------key 9
80DF: not actor $PLAYER_ACTOR driving
004D: jump_if_false @ArrayAct_2
077E: get_active_interior_to 29@
00D6: if 0
0039: 29@ == 0 // integer values
004D: jump_if_false @ArrayAct_2

0247: request_model #fbi

:ArrayAct_3
0001: wait 0 ms
if and
0248: model #fbi available
004D: jump_if_false @ArrayAct_3

:ArrayAct_4
0001: wait 10 ms
00D6: if 0
0256: player $PLAYER_CHAR defined
004D: jump_if_false @ArrayAct_4
if
001B: 10 > 30@ // integer values
004D: jump_if_false @ArrayAct_10
04C4: create_coordinate 24@ 25@ 26@ from_actor $PLAYER_ACTOR offset 0.0 31@ 0.2
009A: 0@(30@,12i) = create_actor_pedtype 6 model #fbi at 24@ 25@ 26@
0187: 10@(30@,12i) = create_marker_above_actor 0@(30@,12i)
000B: 31@ += 2.0 // y自增2.0
000A: 30@ += 1 // 数组索引
0002: jump @ArrayAct_4


:ArrayAct_10
0006: 30@ = 0 // 数组索引

:ArrayAct_11
0001: wait 10 ms
if
0256: player $PLAYER_CHAR defined
004D: jump_if_false @ArrayAct_40
if
001B: 10 > 30@ // integer values
004D: jump_if_false @ArrayAct_15
if
0118: actor 0@(30@,12i) dead
004D: jump_if_false @ArrayAct_13
if
075C: marker 10@(30@,12i) enabled
004D: jump_if_false @ArrayAct_13
0164: disable_marker 10@(30@,12i)
000A: 28@ += 1 // 计数器+1

:ArrayAct_13
000A: 30@ += 1 // 数组索引
if
001B: 10 > 28@ // integer values
004D: jump_if_false @ArrayAct_40
0002: jump @ArrayAct_11

:ArrayAct_15
0006: 30@ = 0 // 数组索引
0002: jump @ArrayAct_11

:ArrayAct_40
0006: 30@ = 0 // 数组索引

:ArrayAct_45
if
001B: 10 > 30@ // integer values
004D: jump_if_false @ArrayAct_50
if
075C: marker 10@(30@,12i) enabled
004D: jump_if_false @ArrayAct_47
0164: disable_marker 10@(30@,12i)

:ArrayAct_47
01C2: remove_references_to_actor 0@(30@,12i) // 设为普通路人
000A: 30@ += 1 // Array index
0002: jump @ArrayAct_45

:ArrayAct_50
0006: 28@ = 0 // 杀死数计数器
0006: 30@ = 0 // 数组索引
0007: 31@ = 2.5 // y偏移
0249: release_model #fbi
0001: wait 1000 ms
0002: jump @ArrayAct_2---------------------------------------------------------------------------------------------------------------------------------------
最后我演示一下如何使用全局变量数组
不过这种方法只能在main.scm中使用,在CLEO中会死机

这稍容易理解,因为它跟我们开头举的例子很像

Family = father
Family = mother
Family = son
Family = doughter
Family = Carl

全局变量就像一个家庭,在方括号内赋予数组索引
$ACTORS = 0
$ACTORS = 0
$ACTORS = 0
$ACTORS = 0
$ACTORS = 0
$ACTORS = 0

数组的结构大概是这样
$ACTORS($ACT_INDEX,30i):Much_Actor_array
03A4: name_thread 'MACTARY'

:LABEL_start
0001: wait 1000 ms
0007: 0@ = -25.0 // 范围
0007: 1@ = 25.0 // 范围
0007: 2@ = 5.0 // X
0007: 3@ = 0.0 // Y
0006: 4@ = 0 // PED ID
0006: 5@ = 0 // PED标示符(handle)
0006: 6@ = 0 // PED生成量计数
0006: 7@ = 29 // PEDs最大数目
0004: $ACTORS = 0 // PED handle
0004: $ACTORS = 0 // PED handle
0004: $ACTORS = 0 // PED handle
0004: $ACTORS = 0 // PED handle
0004: $ACTORS = 0 // PED handle
0004: $ACTORS = 0 // PED handle
0004: $ACTORS = 0 // PED handle
0004: $ACTORS = 0 // PED handle
0004: $ACTORS = 0 // PED handle
0004: $ACTORS = 0 // PED handle
0004: $ACTORS = 0 // PED handle
0004: $ACTORS = 0 // PED handle
0004: $ACTORS = 0 // PED handle
0004: $ACTORS = 0 // PED handle
0004: $ACTORS = 0 // PED handle
0004: $ACTORS = 0 // PED handle
0004: $ACTORS = 0 // PED handle
0004: $ACTORS = 0 // PED handle
0004: $ACTORS = 0 // PED handle
0004: $ACTORS = 0 // PED handle
0004: $ACTORS = 0 // PED handle
0004: $ACTORS = 0 // PED handle
0004: $ACTORS = 0 // PED handle
0004: $ACTORS = 0 // PED handle
0004: $ACTORS = 0 // PED handle
0004: $ACTORS = 0 // PED handle
0004: $ACTORS = 0 // PED handle
0004: $ACTORS = 0 // PED handle
0004: $ACTORS = 0 // PED handle
0004: $ACTORS = 0 // PED handle
0004: $ACT_INDEX = 0

:LABEL_0
0001: wait 0 ms
if
0256: player $PLAYER_CHAR defined
004D: jump_if_false @LABEL_0
if
80DF: not actor $PLAYER_ACTOR driving
004D: jump_if_false @LABEL_0
if
001F: 7@ > $ACT_INDEX // (int)
004D: jump_if_false @LABEL_2
0209: 4@ = random_int_in_ranges 209 264
0247: load_model 4@
038B: load_requested_models

:LABEL_1
0001: wait 0 ms
00D6: if 0
0248: model 4@ available
004D: jump_if_false @LABEL_1
0208: 2@ = random_float_in_ranges 0@ 1@
0208: 3@ = random_float_in_ranges 0@ 1@
04C4: store_coords_to $TEMPVAR_FLOAT_1 $TEMPVAR_FLOAT_2 $TEMPVAR_FLOAT_3 from_actor $PLAYER_ACTOR with_offset 2@ 3@ -1.0
009A: $ACTORS($ACT_INDEX,30i) = create_actor_pedtype 4 model 4@ at $TEMPVAR_FLOAT_1 $TEMPVAR_FLOAT_2 $TEMPVAR_FLOAT_3
05E2: AS_actor $ACTORS($ACT_INDEX,30i) kill_actor $PLAYER_ACTOR
0008: $ACT_INDEX += 1
0002: jump @LABEL_0

:LABEL_2
0004: $ACT_INDEX = 0

:LABEL_3
0001: wait 0 ms
if
0256: player $PLAYER_CHAR defined
004D: jump_if_false @Cleanup_1
if
001F: 7@ > $ACT_INDEX
004D: jump_if_false @LABEL_5
if
8118: not actor $ACTORS($ACT_INDEX,30i) dead
004D: jump_if_false @PED_CREATION_CONTROL_COUNT_UP
0332: set_actor $ACTORS($ACT_INDEX,30i) bleeding 1
0245: set_actor $ACTORS($ACT_INDEX,30i) walk_style_to "oldwoman"
04C4: store_coords_to $TEMPVAR_FLOAT_1 $TEMPVAR_FLOAT_2 $TEMPVAR_FLOAT_3 from_actor $PLAYER_ACTOR with_offset 0.0 0.0 0.0
07CD: AS_actor $ACTORS($ACT_INDEX,30i) walk_to $TEMPVAR_FLOAT_1 $TEMPVAR_FLOAT_2 $TEMPVAR_FLOAT_3 stop_with_angle 0.0 within_radius 1.0

:PED_CREATION_CONTROL_COUNT_UP
0008: $ACT_INDEX += 1
0002: jump @LABEL_3

:LABEL_5
0001: wait 250 ms
if
0256: player $PLAYER_CHAR defined
004D: jump_if_false @Cleanup_1
0002: jump @LABEL_5

:Cleanup_1
0004: $ACT_INDEX = 0

:Cleanup_2
0001: wait 0 ms
if
001F: 7@ > $ACT_INDEX
004D: jump_if_false @Cleanup_3
01C2: remove_references_to_actor $ACTORS($ACT_INDEX,30i)
0008: $ACT_INDEX += 1
0002: jump @Cleanup_2

:Cleanup_3
0002: jump @LABEL_start

为主的祥助 发表于 2012-4-7 10:37:57

本帖最后由 kwanz 于 2012-4-18 18:11 编辑

内存读取

Opcode 0A8D, 0A8C读取内存地址上的内容
首先要了解哪些地址上有函数
你可以在gtamodding.com上找到清单
比如0x863984 – Gravity(重力)

下面是一段读GRAVITY程序,用text_draw opcode显示内存地址上的内容
{$CLEO .cs}
thread 'GRAVITY'
wait 3000
:GRAVITY_1
0A8D: 1@ = read_memory 0x863984 size 4 virtual_protect 1
wait 100
03F0: text_draw_toggle 1
0001: wait 50 ms
03F0: text_draw_toggle 0
0001: wait 50 ms
045A: text_draw_1number 250.0 40.0 'NUMBER' 1@
0A8C: write_memory 0x863984 size 4 value 2 virtual_protect 1 //清除缓存
0A93: end_custom_thread
程序结束处我们把2写入内存,请测试一下程序看看结果
2打进去效果貌似不错,但是如果把浮点值写进去会发生很奇葩的情况
试一下
0A8C: write_memory 0x863984 size 4 value 10.0 virtual_protect 1 //clear the buffer
然后你就会看到树木开始扭曲。。。

更多的内存操作的相关内容请参阅Seemann的帖子SA Memory handling
0A8D: $result = read_memory 1@ size 4 virtual_protect 0

0A8D读取游戏内存并把数据存入变量

参数:
1 – 存入变量(任意变量/数组)
2 – 读取内存地址(整型)
3 – 读取字节数: 1, 2 or 4 bytes
4 – Virtual Protect: 防当机保护。若地址不可读(受保护区域),使用1,否则使用0
0A8C: write_memory 0x00969110 size 4 value 0 virtual_protect 0
0A8C把数值写入游戏内存

参数:
1 – 内存地址(整型)
2 – 写入字节数: 1, 2 or 4 bytes
3 – 写入值(任意数)
4 – Virtual Protect: 防当机保护。若地址只读,使用1,否则使用0

我们可以用地址0x00969110用作模拟作弊码key_press检测
需要用到十六进制的ASCII码表
key_press键码表
40 = @
41 = A
42 = B
43 = C
44 = D
45 = E
46 = F
47 = G
48 = H
49 = I
4A = J
4B = K
4C = L
4D = M
4E = N
4F = O
50 = P
51 = Q
52 = R
53 = S
54 = T
55 = U
56 = V
57 = W
58 = X
59 = Y
5A = Z
5B = [
5C = \
5D =]
5E =^

检测M是否按下,需要从地址0x00969110读入一个字节
0A8D: 1@ = read_memory 0x00969110 size 1 virtual_protect 0

测试按键是否M的十六进制键码
if
04A4: 1@ == 0x4D


check 2 keys: MM
CODE
0A8D: 1@ = read_memory 0x00969110 size 2 virtual_protect 0
if
04A4: 1@ == 0x4D4D
检测4个键: WILD
0A8D: 1@ = read_memory 0x00969110 size 4 virtual_protect 1
if
04A4: 1@ == 0x57494C44 //检测1@ = WILD
下面的程序当输入JUMP的时候启动超级跳作弊
{$CLEO .cs}
thread 'cheat'

:Cheatcode_1
wait 0
0A8D: 1@ = read_memory 0x00969110 size 4 virtual_protect 0
if
04A4: 1@ == 0x4A554D50 //检测1@ = JUMP
004D: jump_if_false @Cheatcode_1
03E5: text_box 'CHEAT1'
0109: player $PLAYER_CHAR money += 1000000
0A8C: write_memory 0x00969110 size 4 value 0 virtual_protect 0 //清除缓存
0A8C: write_memory 0x96916C size 4 value 1 virtual_protect 0 //-- 启动作弊
0A93: end_custom_thread
要检测多于4个字符,需要用到额外的内存地址0x00969114
原理是:首先把前面4个字符存入这个地址,然后剩下的1/2/4个字符存入0x00969110

下面的程序在输入JUMPRAMP的时候刷出一个特技跳斜坡
{$CLEO .cs}
thread 'cheat'

:Cheatcode_1
wait 0
0A8D: 1@ = read_memory 0x00969110 size 4 virtual_protect 0 //
0A8D: 2@ = read_memory 0x00969114 size 4 virtual_protect 0 //
if and
04A4: 1@ == 0x52414D50 //检测1@ = RAMP
04A4: 2@ == 0x4A554D50 //检测2@ = JUMP
004D: jump_if_false @Cheatcode_1
03E5: text_box 'CHEAT1'
0109: player $PLAYER_CHAR money += 1000000
0A8C: write_memory 0x00969110 size 4 value 0 virtual_protect 0 //清除缓存
0A8C: write_memory 0x00969114 size 4 value 0 virtual_protect 0 //清除缓存
0247: request_model 1655

:Cheatcode_JRamp
0001: wait 0 ms
00D6: if 0
0248: model 1655 available
004D: jump_if_false @Cheatcode_JRamp
0172: 2@ = actor $PLAYER_ACTOR z_angle
04C4: create_coordinate 11@ 12@ 13@ from_actor $PLAYER_ACTOR offset 0.0 14.5 -1.8
0107: 1@ = create_object 1655 at 11@ 12@ 13@
0177: set_object 1@ z_angle_to 2@
0001: wait 0 ms
0249: release_model 1655
0001: wait 1000 ms
01C4: remove_references_to_object 1@ // 解除引用,物品会在玩家视角移开以后刷掉
0002: jump @Cheatcode_1
输入ARMOUR在Grove St刷一件防弹衣
{$CLEO .cs}
thread 'cheat'

:Cheatcode_1//ARMOUR
wait 0
0A8D: 1@ = read_memory 0x00969110 size 4 virtual_protect 0 //
0A8D: 2@ = read_memory 0x00969114 size 2 virtual_protect 0 //
if and
04A4: 1@ == 0x4D4F5552//MOUR
04A4: 2@ == 0x4152//AR
004D: jump_if_false @Cheatcode_1
03E5: text_box 'CHEAT1'
0109: player $PLAYER_CHAR money += 1000000
0A8C: write_memory 0x00969110 size 4 value 0 virtual_protect 0 //清除缓存
0A8C: write_memory 0x00969114 size 2 value 0 virtual_protect 0 //清除缓存
Pickup.Create(0@, 1242, 3, 2495.1387, -1680.1288, 13.3388)
0002: jump @Cheatcode_1

引用 (Rapier @ Aug 31 2009, 04:05)
引用 (ZAZ @ Jun 5 2009, 18:34)
我们可以用地址0x00969110用作模拟作弊码key_press检测
这个地址是1.0用的,那1. 1呢?

引用 (Wesser @ Aug 31 2009, 07:21)
1.10地址为0x96B790.

为主的祥助 发表于 2012-4-7 10:38:18

本帖最后由 kwanz 于 2012-4-18 18:14 编辑

调用scm函数

引用 (The_Siggi's sent pm)
额,这个之前已经解释过,在这里我再讲解一下
调0AB1就类似004F,但它可以通过调0485/059A返回TRUE/FALSE;但这时调用函数必须以不带返回值的0AB2结束,不然游戏会挂。这些opcode在你想写条件判断函数的时候很有用。
在单用0AB2时,可以返回任意值
外部线程
0AB1的格式如下:call_scm_func <线程> <参数数目> | <参数1> <参数2> ...参数数和前面的数目一致。所有的参数可以是数值或局部/全局变量,传入时各占一个独立的偏移量。

被调线程(函数线程)
所有传入的参数都存储在从0开始连续的偏移位置上,即参数1存为0@,参数2存为1@...如此类推,直到到达局部变量的最大偏移(33@)记得用类似格式的0AB2结束调用函数0AB2: ret <参数数目> | <参数1> <参数2> ...如果函数返回至少一个参数,0AB1应该改造如下,以存入返回值0AB1: call_scm_func <线程> <传入参数数> | <入参1> <入参2> ... | <出参1> <出参2> ...自定义函数示例
条件判断函数[...]
if
0AB1: call_scm_func @isActorDriving 1 actor $PLAYER_ACTOR
then
03C0: 0@ = actor $PLAYER_ACTOR car
end
[...]

:isActorDriving
{
0@ - actor
}
if
00DF: actor 0@ driving
then
0485: return_true
else
059A: return_false
end
0AB2: ret 0写入参数[...]
0AB1: call_scm_func @setActorHealth 2 actor $PLAYER_ACTOR health 100
[...]

:setActorHealth
{
0@ - actor
1@ - health
}
0223: set_actor 0@ health_to 1@
0AB2: ret 0读取参数[...]
0AB1: call_scm_func @getActorArmour 1 actor $PLAYER_ACTOR armour_to 10@
[...]

:getActorArmour
{
0@ - actor
}
04DD: 1@ = actor 0@ armour
0AB2: ret 1 1@读取/写入[...]
00A0: store_actor $PLAYER_ACTOR position_to 1@ 2@ 3@
0AB1: call_scm_func @getRandomPos 4 in 1@ 2@ 3@ radius 4@ out_to 5@ 6@ 7@
[...]

:getRandomPos
{
0@ - X pos
1@ - Y pos
2@ - Z pos
3@ - radius
}
0087: 4@ = 0@
0087: 5@ = 1@
0063: 4@ -= 3@
0063: 5@ -= 3@
005B: 0@ += 3@
005B: 1@ += 3@
0@ = random(4@, 0@)
1@ = random(5@, 1@)
02CE: 2@ = ground_z_at 1@ 2@ 3@
0AB2: ret 3 0@ 1@ 2@0AB1:最多可带多少个参数?
引用 (Wesser @ Jul 26 2010, 15:50)
我猜最多为34个参数,因为参数在被调函数中存储为0@到33@
下面的程序类似SB的示例文件,演示了如何不使用gxt/fxt数据显示文本
作者Rapier{$CLEO}

thread 'MSG_TEST'
wait 5000
0AB1: call_scm_func @LabelMSGMain 1 @LabelMSG01
wait 5000
0AB1: call_scm_func @LabelMSGMain 1 @LabelMSG02
0A93: end_custom_thread

:LabelMSGMain
0A9F: 1@ = current_thread_pointer
1@ += 16
0A8D: 1@ = read_memory 1@ size 4 virtual_protect 0
0062: 1@ -= 0@ // (int)
1@ += 4
if
0AA9: is_game_version_original
jf @LabelMSGVersion101
0AA5: call 0x588BE0 num_params 4 pop 4 0 0 0 1@ // v1.0
jump @LabelMSGMain02

:LabelMSGVersion101
0AA5: call 0x5893B0 num_params 4 pop 4 0 0 0 1@ // v1.01

:LabelMSGMain02
0AB2: ret 0

:LabelMSG01
0900: "You are playing..."

:LabelMSG02
0900: "GTA San Andreas"
0000: nop相关话题
高级内存访问帮助/基础教程

为主的祥助 发表于 2012-4-7 10:38:32

本帖最后由 kwanz 于 2012-4-18 18:15 编辑

_____________________________________________________________________________________
在代码中访问随机路人
若干个opcode可以在某地获取随机人物的访问:089E: get_actor_in_sphere 3@ 4@ 5@ radius 5.0 handle_as 11@ // versionB
08E5: get_actor_in_sphere 27@ 28@ 29@ radius 50.0 handle_as 0@
073F: get_actor_in_sphere 4@ 7@ 10@ radius 20.0 with_pedtype_civilian 1 gang 1 criminal/prostitute 1 handle_as 27@但这几个都不能获取帮派成员,药品贩子等特殊人物,尤其是任务里的特殊人物。
另外还有一个opcode0AB5: store_actor $PLAYER_ACTOR closest_vehicle_to 0@ closest_ped_to 1@但它只能获得最近的一个人物,对其他人无能为力。
并且,如果在四下无人的地方用这些opcode,游戏会挂。。。
------------------------------------------------------------------------------------------------------
我坛的Wesser发过一个方法可以获取游戏世界的每一个人物,包括任务人物,外部脚本(包括CLEO)使用的人物;只有食品摊子,比如快餐店的人物除外。
Wesser的源程序是这样用的:call_func @getActorInSphere
他使用了上一节中解释过的0AB1: call_func
以及多种程序语言中用到,SB支持的按步长循环结构(for-to-step)
for循环重复执行一个代码块,循环变量等差递增
Deji写了一个更加简单快速的版本
为了解释清楚,我把Wesser的程序改成了下面的例子,GTA实测可用,包括:
1. 带opcode版本
2. 不带opcode版本
程序获取一个随机人物,显示他的PED类别,然后把他杀死。

1. 带opcode版本{$CLEO .cs}
:RandomActor_for_to_step_method
thread 'RAFSTEP'

:RAFSTEP_1
0001: wait 0 ms
00D6: if
0256: player $PLAYER_CHAR defined
004D: jump_if_false @RAFSTEP_1
00A0: store_actor $PLAYER_ACTOR position_to 1@ 2@ 3@
0AB1: call_scm_func @RAFSTEP_func 4 1@ 2@ 3@ 5.0 0@
00D6: if
8039: not 0@ == -1
004D: jump_if_false @RAFSTEP_1
00D6: if
8118: not actor 0@ dead
004D: jump_if_false @RAFSTEP_1
089F: get_actor 0@ pedtype_to 31@
03F0: enable_text_draw 1
0001: wait 50 ms
03F0: enable_text_draw 0
0001: wait 50 ms
045A: draw_text_1number 250.0 40.0 GXT 'NUMBER' number 31@ // ~1~
05BE: AS_kill_actor 0@
01C2: remove_references_to_actor 0@ // 设为普通路人
0002: jump @RAFSTEP_1

:RAFSTEP_func
0006: 5@ = 0
0006: 4@ = 0

:RAFSTEP_countLoop
00D6: if
056D: actor 4@ defined
004D: jump_if_false @RAFSTEP_11
00D6: if and
803B: not $PLAYER_ACTOR == 4@ // (int)
00FE: actor 4@ sphere 0 in_sphere 0@ 1@ 2@ radius 3@ 3@ 3@
004D: jump_if_false @RAFSTEP_11
0006: 5@ = 1
0002: jump @RAFSTEP_12

:RAFSTEP_11
000A: 4@ += 1
00D6: if
0019: 4@ > 30000
004D: jump_if_false @RAFSTEP_countLoop

:RAFSTEP_12
00D6: if
0039: 5@ == 0
004D: jump_if_false @RAFSTEP_Result
0006: 4@ = -1

:RAFSTEP_Result
0AB2: ret 1 4@2. 不带opcode版本{$CLEO .cs}
:RandomActor_for_to_step_method
thread 'RAFSTEP'

:RAFSTEP_1
wait 0
if
Player.Defined($PLAYER_CHAR)
jf @RAFSTEP_1
Actor.StorePos($PLAYER_ACTOR, 1@, 2@, 3@)
0AB1: call_scm_func @RAFSTEP_func 4 1@ 2@ 3@ 5.0 0@
if
not 0@ == -1
jf @RAFSTEP_1
if
not Actor.Dead(0@)
jf @RAFSTEP_1
089F: get_actor 0@ pedtype_to 31@
03F0: enable_text_draw 1
wait 50
03F0: enable_text_draw 0
wait 50
045A: draw_text_1number 250.0 40.0 GXT 'NUMBER' number 31@ // ~1~
05BE: AS_kill_actor 0@
Actor.RemoveReferences(0@)
jump @RAFSTEP_1

:RAFSTEP_func
5@ = 0
4@ = 0

:RAFSTEP_countLoop
if
Actor.Defined(4@)
jf @RAFSTEP_11
if and
803B: not $PLAYER_ACTOR == 4@ // (int)
00FE: actor 4@ sphere 0 in_sphere 0@ 1@ 2@ radius 3@ 3@ 3@
jf @RAFSTEP_11
5@ = 1
jump @RAFSTEP_12

:RAFSTEP_11
4@ += 1
if
4@ > 30000
jf @RAFSTEP_countLoop

:RAFSTEP_12
if
5@ == 0
jf @RAFSTEP_Result
4@ = -1

:RAFSTEP_Result
0AB2: ret 1 4@

为主的祥助 发表于 2012-4-7 10:39:27

本帖最后由 kwanz 于 2012-4-13 19:22 编辑

车辆行驶编写教程
___
引用 (markbaker @ Aug 26 2009, 12:36)
很给力的教程!

我有几个简单的问题 - 如何刷出车辆并让它自己行驶,直线驾驶抑或走特定路径?还有,能否生成有行人做驾驶员或乘客的车辆?
___
首先让我们从最简单的问题开始:“如何刷车”,我直接拉教程Scripting/Writing a Thread -- Next Step/ Spawn a 3D model里的例子过来

下面的代码当玩家入圈时在Grove St刷出Infernus
玩家离开后,代码会释放对车辆的引用,跳回判断外循环
{$CLEO .cs}
:3dModels_1
03A4: name_thread 'MODL'

:3dModels_2
0001: wait 0 ms
00D6: if 0
0256: player $PLAYER_CHAR defined
004D: jump_if_false @3dModels_2
00D6: if 0
00FF: actor $PLAYER_ACTOR 1 (in-sphere)near_point_on_foot 2491.5 -1667.5 13.35 radius 1.0 1.0 1.0
004D: jump_if_false @3dModels_2

0247: request_model #INFERNUS

:Load_Model_Check
0001: wait 0 ms
00D6: if 0
0248: model #INFERNUS available
004D: jump_if_false @Load_Model_Check

00A5: 1@ = create_car #INFERNUS at 2487.5 -1660.5 13.35
0175: set_car 1@ z_angle_to 90.0
0249: release_model #INFERNUS

:3dModels_3
0001: wait 0 ms
00D6: if 0
0256: player $PLAYER_CHAR defined
004D: jump_if_false @3dModels_3
00D6: if 0
80FF: NOT actor $PLAYER_ACTOR 0 ()near_point_on_foot 2491.5 -1667.5 13.35 radius 2.0 2.0 2.0
004D: jump_if_false @3dModels_3
01C3: remove_references_to_car 1@ // 解除对车辆的引用,车子变成一辆普通的随机街车
0002: jump @3dModels_2

下一步,我在车上刷出两个人物,让车子开往指定地点
更进一步,我在车上放了个箭头,你可以在小地图上看车子开到哪儿

刷出人物只需要直接调opcode: 0129刷司机,01C8刷乘客
当然也可以用正常的刷人代码,然后让人物上车,同样的对司机和乘客用不同的opcode
乘客上车opcode需要设定最后一个参数为座椅号
0=副驾,1/2为后排

让车辆行驶,我直接使用了简单的drive_to
行驶指令有很多变体,所有的用法都需要设定速度

drive-to命令后的循环需要对车辆的行驶动作的条件判定
有一个重要的检查就是判断车辆废了没有
比如说,程序里设定的人物死了,被捕,或者车子毁了开远了,我们需要用些法子执行刷新,也就是解除对车辆,箭头和乘客的引用,来从头开始执行代码。
if or
0119: car 1@ wrecked
01F4: car 1@ flipped
8202: not actor $PLAYER_ACTOR near_car 1@ radius 500.0 500.0 flag 0
下面的代码在玩家进圈时在老家刷出Infernus,车上有两个小弟
玩家进圈后,车辆会开到下一个路口并停止,直到玩家离车足够远(500.0单位)
CODE
{$CLEO .cs}
:CarDrive_1
03A4: name_thread 'CDRIVE'

:CarDrive_2
0001: wait 0 ms
if
0256: player $PLAYER_CHAR defined
004D: jump_if_false @CarDrive_2
if
00FF: actor $PLAYER_ACTOR 1 (in-sphere)near_point_on_foot 2491.5 -1667.5 13.35 radius 1.0 1.0 1.0
004D: jump_if_false @CarDrive_2

0247: request_model #INFERNUS
0247: request_model #fam1
0247: request_model #fam2

:CarDrive_3
0001: wait 0 ms
if and
0248: model #INFERNUS available
0248: model #fam1 available
0248: model #fam2 available
004D: jump_if_false @CarDrive_3

00A5: 1@ = create_car #INFERNUS at 2487.5 -1660.5 13.35
0175: set_car 1@ z_angle_to 90.0
0129: 2@ = create_actor 8 #fam1 in_car 1@ driverseat
01C8: 3@ = create_actor 8 #fam2 in_car 1@ passenger_seat 0
0186: 4@ = create_marker_above_car 1@
07E0: set_marker 4@ type_to 1

0249: release_model #INFERNUS
0249: release_model #fam1
0249: release_model #fam2

//////////////////// drive_to块开始

00A7: car 1@ drive_to 2353.1528 -1658.6493 13.3846//---简单的drive_to
00AD: set_car 1@ max_speed_to 20.0//---设定速度,很重要
00AE: unknown_set_car 1@ to_ignore_traffic_lights 2//--可选,设定车辆遵守交通规则

//////////////////// drive_to块结束

:CarDrive_13
0001: wait 0 ms
if
0256: player $PLAYER_CHAR defined
004D: jump_if_false @CarDrive_13
if or
0119: car 1@ wrecked
01F4: car 1@ flipped
8202: not actor $PLAYER_ACTOR near_car 1@ radius 500.0 500.0 flag 0
004D: jump_if_false @CarDrive_13
01C3: remove_references_to_car 1@ // 解除引用,设为随机车辆
01C2: remove_references_to_actor 2@ // 解除引用,设为普通路人
01C2: remove_references_to_actor 3@ // 解除引用,设为普通路人
0164: disable_marker 4@
0002: jump @CarDrive_2

让车辆行驶还有很多变体。最简单的例子是00A7
车辆会严格按照path行驶,path存储在gta3.img中的nodes.dat里,是交通车辆的行驶路径。如果你在没有path的地方刷车,比如沙漠里,然后调行驶命令,它首先会开到path上,然后走path到目的地。如果目的地不在path上,车子是到不了的。
写车辆行驶代码是让人非常恼火的事情,即便目的地在path上。它经常不走寻常路,或者卡住。
----------------------------------------------------------------------------
我们还有别的opcode强行控制车辆
----------------------------------------------------------------------------

opcode 04e0: 让车辆忽略path直接开往目的地
04e0: car 1@ abandon_path_radius 200

用下面的代码块换掉上面的drive_to块
//////////////////// drive-to块开始

00A7: car 1@ drive_to 2431.5864 -1628.0818 13.698//---简单的drive_to
00AD: set_car 1@ max_speed_to 20.0//---设定速度,很重要
00AE: unknown_set_car 1@ to_ignore_traffic_lights 2//--可选,设定车辆忽略交通灯并绕过其他车辆
04e0: car 1@ abandon_path_radius 200

//////////////////// drive-to块结束
目的地是Grove St和高速公路之间的空地
若没有04e0:,车辆会在路上开很远
opcode 04e0: 仅在一定半径范围内有效
它表示起点要在path的200单位范围内,目的地也一样
大于250则失效
----------------------------------------------------------------------------
用opcode 00AF: 并设最后一个参数为2,车辆会追玩家
//////////////////// drive-to块开始

00AD: set_car 1@ max_speed_to 20.0//---设定速度,很重要
00AE: unknown_set_car 1@ to_ignore_traffic_lights 2//--可选,设定车辆忽略交通灯并绕过其他车辆
00AF: set_car 1@ driver_behaviour_to 2//-- 追着玩家

//////////////////// drive-to块结束

opcode 00AF可以接受4种行为设定
1 - 在道路上开,如果道路被堵,就倒车
2 - 杀死玩家
4 - 开向玩家并停车
8 - 忽略所有路径
----------------------------------------------------------------------------
用opcode 00AF: 并设最后一个参数为2,车辆会自动沿path行驶
//////////////////// drive-to块开始

00AD: set_car 1@ max_speed_to 20.0//---设定速度,很重要
00AE: unknown_set_car 1@ to_ignore_traffic_lights 2//--可选,设定车辆忽略交通灯并绕过其他车辆
00AF: set_car 1@ driver_behaviour_to 1

//////////////////// drive-to块结束
----------------------------------------------------------------------------
我们可以用opcode读车前坐标,并让车子行驶到此处
//////////////////// drive-to块开始

0407: create_coordinate 11@ 12@ 13@ from_car 1@ offset -10.0 15.0 0.0
00A7: car 1@ drive_to 11@ 12@ 13@//---简单的drive-to
00AD: set_car 1@ max_speed_to 20.0//---设定速度,很重要
00AE: unknown_set_car 1@ to_ignore_traffic_lights 2//--可选,设定车辆忽略交通灯并绕过其他车辆

//////////////////// drive-to块结束
----------------------------------------------------------------------------
我们可以用opcode读车前坐标,并让车子行驶到此处;并且调04BA执行瞬时加速
//////////////////// drive-to块开始

0407: create_coordinate 11@ 12@ 13@ from_car 1@ offset -10.0 15.0 0.0
00A7: car 1@ drive_to 11@ 12@ 13@//---简单的drive-to
00AD: set_car 1@ max_speed_to 20.0//---设定速度,很重要
00AE: unknown_set_car 1@ to_ignore_traffic_lights 2//--可选,设定车辆忽略交通灯并绕过其他车辆
04BA: set_car 1@ speed_instantly 50.0

//////////////////// drive-to块结束


----------------------------------------------------------------------------
让司机执行行驶纠正
R*在main.scm里有车辆堵塞检测,但这个函数在CLEO中无效
不过可以调06C7做行驶纠正
//////////////////// drive-to块开始

06C7: AS_actor 2@ driver_of_car 1@ perform_action 14 timelimit 3000 // 倒车设定
00A7: car 1@ drive_to 2353.1528 -1658.6493 13.3846//---简单的drive-to
00AD: set_car 1@ max_speed_to 20.0//---设定速度,很重要
00AE: unknown_set_car 1@ to_ignore_traffic_lights 2//--可选,设定车辆忽略交通灯并绕过其他车辆

//////////////////// drive-to块结束
司机首先会做约3秒的转圈倒车,然后开往目的地
----------------------------------------------------------------------------
Opcode 06C7还有一些不同版本
06C7: AS_actor 2@ driver_of_car 1@ perform_action 6 timelimit 1000 //短暂停车
06C7: AS_actor 2@ driver_of_car 1@ perform_action 6 timelimit 2000000 //长时间停车
06C7: AS_actor 2@ driver_of_car 1@ perform_action 3 timelimit 3000 //倒车向右,然后前进
06C7: AS_actor 2@ driver_of_car 1@ perform_action 22 timelimit 3000 //倒车向左,然后前进
06C7: AS_actor 2@ driver_of_car 1@ perform_action 14 timelimit 3000 //倒车转圈
06C7: AS_actor 2@ driver_of_car 1@ perform_action 9 timelimit 3000 //加速前进
06C7: AS_actor 2@ driver_of_car 1@ perform_action 7 timelimit 3000 //左转
06C7: AS_actor 2@ driver_of_car 1@ perform_action 8 timelimit 3000 //右转
----------------------------------------------------------------------------
指定司机驾车

Opcode 05D1不是控制车辆的指令,它是作用于司机的

这个函数也可以忽略path,让司机直线开向目的地,正如04e0: car 1@ abandon_path_radius
这取决于标志位的设定

0 0 5 沿path
2 0 5 忽略path
//////////////////// drive-to块开始

05D1: AS_actor 2@ drive_car 1@ to 2353.1528 -1658.6493 13.384 speed 20.0 0 0 5

//////////////////// drive-to块结束
----------------------------------------------------------------------------
Opcode 05D1可被调用多次来设定AS_Pack的组合动作
调用的时候需要设定驾驶员参数为-1,并在设置完AS_Pack后将人物2@赋给该AS_Pack
//////////////////// drive-to块开始

0615: define_action_sequences 5@
05D1: AS_actor -1 drive_car 1@ to 2353.1528 -1658.6493 13.384 speed 20.0 0 0 5
05D1: AS_actor -1 drive_car 1@ to 2431.7739 -1674.7444 13.6643 speed 20.0 0 0 5
05D1: AS_actor -1 drive_car 1@ to 2431.5864 -1628.0818 13.698 speed 20.0 2 0 5
0616: define_action_sequences_end 5@
0618: assign_actor 2@ to_action_sequences 5@
061B: remove_references_to_AS_pack 5@

//////////////////// drive-to块结束
----------------------------------------------------------------------------
为司机定义scmpath

先调用05D6清除先前设定的scmpath
然后设定新的坐标,然后调07E7让司机沿路径驾驶

这个函数也可以设定为忽略路径,让司机直线行驶,正如04E0: car 1@ abandon_path_radius
这取决于标志位的设定

0 0 5 沿path
2 0 5 忽略path
//////////////////// drive-to块开始

05D6: clear_scmpath
05D7: add_point_to_scmpath 2353.1528 -1658.6493 13.384
05D7: add_point_to_scmpath 2431.7739 -1674.7444 13.6643
07E7: AS_assign_scmpath_to_actor 2@ in_car 1@ speed 20.0 flags 0 0 5

//////////////////// drive-to块结束
----------------------------------------------------------------------------
车辆行驶脚本的实际应用
----------------------------------------------------------------------------
在实际写车辆沿指定的长路径行驶的时候需要写比较复杂的代码,不断检测车辆是否到达检查点并设定下一个路点。因为你不能等车到了地方以后才检查车辆的位置,你必须要沿路经过时做检查
并且,程序需要检测车子是否飞到了空中,因为此时它会丢失坐标信息,我们必须补充相关的信息
检测是否翻车或毁车永远是必要的,因为车子废了就不能继续开,程序结束
R*在main.scm中用到了车辆堵塞检测,但这个函数在CLEO中不可用
不过我们可以检测车速是否低于1.0
----------------------------------------------------------------------------
SF机场环行程序V1
以下的脚本把玩家传送到SF机场,坐上摩托车,并且刷出骑车绕机场大楼转圈的人物
请走到室外空间,按退格键,跟着这个NPC看看
这里用到了Opcode 00A7: car 1@ drive_to和04e0: car 1@ abandon_path_radius
这人有时会摔下车,然后上车继续跑
作为替代,你也可以调08C6
//08C6: set_actor 9@ stay_on_bike 1

要刷新这段代码你需要离机场足够远,至少700.0单位
CODE
{$CLEO .cs}
:Drive_1
03A4: name_thread 'DRIV'

:Drive_3
0001: wait 0 ms
if
0256: player $PLAYER_CHAR defined
jf @Drive_3
077E: 0@ = active_interior
if and
0039: 0@ == 0 // integer values
0AB0: key_pressed 8//----------------------------------------Backspace
jf @Drive_3
016A: fade 0 () 250 ms
0001: wait 250 ms
01B4: set_player $PLAYER_CHAR frozen_state 0 (frozen)
0362: remove_actor $PLAYER_ACTOR from_car_and_place_at -1338.5 -408.1 14.1
0173: set_actor $PLAYER_ACTOR z_angle_to 90.8
0001: wait 500 ms
0247: request_model #NRG500
0247: request_model #MAFFA

:Drive_5
0001: wait 0 ms
if and
0248: model #NRG500 available
0248: model #MAFFA available
jf @Drive_5
00A5: 1@ = create_car #NRG500 at -1333.5 -408.1 14.1
0175: set_car 1@ z_angle_to 280.0
0224: set_car 1@ health_to 2000
00A5: 7@ = create_car #NRG500 at -1354.5 -419.1 14.1
0175: set_car 7@ z_angle_to 280.0
0224: set_car 7@ health_to 2000
020A: set_car 7@ door_status_to 4
02AC: set_car 7@ immunities 1 1 1 1 1
01EC: make_car 7@ very_heavy 1
0129: 9@ = create_actor 24 #MAFFA in_car 7@ driverseat
0223: set_actor 9@ health_to 3000
04E4: unknown_refresh_game_renderer_at -1333.5 -408.1
03CB: set_camera -1333.5 -408.1 14.1
029B: 23@ = init_object 1655 at -1576.02 -202.34 13.76
0177: set_object 23@ z_angle_to 270.0
01C7: remove_object_from_mission_cleanup_list 23@
0382: set_object 23@ collision_detection 1
029B: 24@ = init_object 1655 at -1597.9 -506.5 21.7
0177: set_object 24@ z_angle_to 270.0
01C7: remove_object_from_mission_cleanup_list 24@
0382: set_object 24@ collision_detection 1
029B: 25@ = init_object 1655 at -1375.9 -581.5 13.69
0177: set_object 25@ z_angle_to 270.0
01C7: remove_object_from_mission_cleanup_list 25@
0382: set_object 25@ collision_detection 1
029B: 26@ = init_object 1655 at -1374.9 -585.5 13.69
0177: set_object 26@ z_angle_to 270.0
01C7: remove_object_from_mission_cleanup_list 26@

0382: set_object 26@ collision_detection 1
0177: set_object 23@ z_angle_to 135.0
0177: set_object 24@ z_angle_to 225.0
0177: set_object 25@ z_angle_to 280.0
0177: set_object 26@ z_angle_to 280.0
0186: 29@ = create_marker_above_car 7@
07E0: set_marker 29@ type_to 1

0249: release_model #NRG500
0249: release_model #MAFFA
04e0: car 7@ abandon_path_radius 200
00AD: set_car 7@ max_speed_to 100.0
04BA: set_car 7@ speed_instantly 30.0
00AF: set_car 7@ driver_behaviour_to 1
00AE: unknown_set_car 7@ to_ignore_traffic_lights 2
0001: wait 250 ms
036A: put_actor $PLAYER_ACTOR in_car 1@
0001: wait 250 ms
016A: fade 1 () 1000 ms
0001: wait 1000 ms
0373: set_camera_directly_behind_player
02EB: restore_camera_with_jumpcut
01B4: set_player $PLAYER_CHAR frozen_state 1 (unfrozen)
0006: 15@ = 0 // integer values
0006: 16@ = 0 // integer values
0006: 20@ = 20000 // floating-point values
0006: 19@ = 0 // integer values
0007: 11@ = -1320.48 // floating-point values
0007: 12@ = -407.1 // floating-point values
0007: 13@ = 13.76 // floating-point values
00A7: car 7@ drive_to 11@ 12@ 13@
00AD: set_car 7@ max_speed_to 1.0
04e0: car 7@ abandon_path_radius 250
//08C6: set_actor 9@ stay_on_bike 1

:Drive_7
0001: wait 0 ms
if
0256: player $PLAYER_CHAR defined
jf @Drive_7

0050: gosub @Drive_sub_3

if and
8119: NOT car 1@ wrecked
8119: NOT car 7@ wrecked
8118: NOT actor 9@ dead
jf @Drive_7
if
00FE: actor $PLAYER_ACTOR 0 ()near_point -1333.5 -408.1 14.1 radius 650.5 650.5 50.5
jf @Drive_12
jump @Drive_7

:Drive_12
0164: disable_marker 29@
01C3: remove_references_to_car 1@ // 转为随机车辆
01C3: remove_references_to_car 7@ //转为随机车辆
01C2: remove_references_to_actor 9@ //转为随机人物
0108: destroy_object 23@
0108: destroy_object 24@
0108: destroy_object 25@
0108: destroy_object 26@
jump @Drive_3


:Drive_sub_3
if
8119: NOT car 7@ wrecked
jf @Drive_sub_109
if
00DB: actor 9@ in_car 7@
jf @Drive_sub_99
if
0039: 19@ == 1 // integer values
jf @Drive_sub_10
0006: 19@ = 0 // integer values
jump @Drive_sub_100

:Drive_sub_10
if
0039: 15@ == 0 // integer values
jf @Drive_sub_11
if
01AF: car 7@ 0 ()near_point 11@ 12@ 13@ radius 5.2 5.2 5.0
jf @Drive_sub_11
0006: 15@ = 1 // integer values
0007: 11@ = -1181.78 // floating-point values
0007: 12@ = -331.30 // floating-point values
0007: 13@ = 13.76 // floating-point values
000A: 16@ += 0 // integer values
0007: 17@ = 100.0 // floating-point values
0007: 18@ = 20.0 // floating-point values
04e0: car 7@ abandon_path_radius 250
jump @Drive_sub_100

:Drive_sub_11
if
0039: 15@ == 1 // integer values
jf @Drive_sub_12
if
01AF: car 7@ 0 ()near_point 11@ 12@ 13@ radius 15.2 15.2 5.0
jf @Drive_sub_12
00AD: set_car 7@ max_speed_to 10.0
0006: 15@ = 2 // integer values
0007: 11@ = -1282.1 // floating-point values
0007: 12@ = -159.3 // floating-point values
0007: 13@ = 13.76 // floating-point values
0175: set_car 7@ z_angle_to 340.0
000A: 16@ += 0 // integer values
0007: 17@ = 100.0 // floating-point values
0007: 18@ = 20.0 // floating-point values
04e0: car 7@ abandon_path_radius 250
jump @Drive_sub_100

:Drive_sub_12
if
0039: 15@ == 2 // integer values
jf @Drive_sub_13
if
01AF: car 7@ 0 ()near_point 11@ 12@ 13@ radius 15.2 15.2 5.0
jf @Drive_sub_13
00AD: set_car 7@ max_speed_to 25.0
0006: 15@ = 3 // integer values
0007: 11@ = -1498.78 // floating-point values
0007: 12@ = -138.30 // floating-point values
0007: 13@ = 13.76 // floating-point values
0175: set_car 7@ z_angle_to 65.0
000A: 16@ += 0 // integer values
0007: 17@ = 100.0 // floating-point values
0007: 18@ = 20.0 // floating-point values
04e0: car 7@ abandon_path_radius 250
jump @Drive_sub_100

:Drive_sub_13
if
0039: 15@ == 3 // integer values
jf @Drive_sub_14
if
01AF: car 7@ 0 ()near_point 11@ 12@ 13@ radius 8.2 8.2 5.0
jf @Drive_sub_14
00AD: set_car 7@ max_speed_to 25.0
0006: 15@ = 4 // integer values
0007: 11@ = -1576.78 // floating-point values
0007: 12@ = -202.30 // floating-point values
0007: 13@ = 13.76 // floating-point values
0175: set_car 7@ z_angle_to 135.0
000A: 16@ += 0 // integer values
0007: 17@ = 100.0 // floating-point values
0007: 18@ = 20.0 // floating-point values
04e0: car 7@ abandon_path_radius 250
jump @Drive_sub_100



:Drive_sub_14
if
0039: 15@ == 4 // integer values
jf @Drive_sub_15
if
01AF: car 7@ 0 ()near_point 11@ 12@ 13@ radius 5.2 5.2 5.0
jf @Drive_sub_15
0006: 15@ = 5 // integer values
0007: 11@ = -1694.78 // floating-point values
0007: 12@ = -352.30 // floating-point values
0007: 13@ = 13.9 // floating-point values
0175: set_car 7@ z_angle_to 135.0
000A: 16@ += 0 // integer values
0007: 17@ = 100.0 // floating-point values
0007: 18@ = 20.0 // floating-point values
04e0: car 7@ abandon_path_radius 250
jump @Drive_sub_100

:Drive_sub_15
if
0039: 15@ == 5 // integer values
jf @Drive_sub_16
if
01AF: car 7@ 0 ()near_point 11@ 12@ 13@ radius 15.2 15.2 5.0
jf @Drive_sub_16
00AD: set_car 7@ max_speed_to 10.0
0006: 15@ = 6 // integer values
0007: 11@ = -1691.78 // floating-point values
0007: 12@ = -409.30 // floating-point values
0007: 13@ = 13.9 // floating-point values
0175: set_car 7@ z_angle_to 180.0
000A: 16@ += 0 // integer values
0007: 17@ = 40.0 // floating-point values
0007: 18@ = 10.0 // floating-point values
04e0: car 7@ abandon_path_radius 250
00AE: unknown_set_car 7@ to_ignore_traffic_lights 2
jump @Drive_sub_100

:Drive_sub_16
if
0039: 15@ == 6 // integer values
jf @Drive_sub_17
if
01AF: car 7@ 0 ()near_point 11@ 12@ 13@ radius 8.2 8.2 5.0
jf @Drive_sub_17
00AD: set_car 7@ max_speed_to 0.0
0006: 15@ = 7 // integer values
0007: 11@ = -1519.78 // floating-point values
0007: 12@ = -580.30 // floating-point values
0007: 13@ = 13.76 // floating-point values
0175: set_car 7@ z_angle_to 250.0
000A: 16@ += 0 // integer values
0007: 17@ = 100.0 // floating-point values
0007: 18@ = 0.0 // floating-point values
04e0: car 7@ abandon_path_radius 250
00AE: unknown_set_car 7@ to_ignore_traffic_lights 2
jump @Drive_sub_100

:Drive_sub_17
if
0039: 15@ == 7 // integer values
jf @Drive_sub_18
if
01AF: car 7@ 0 ()near_point 11@ 12@ 13@ radius 15.2 15.2 5.0
jf @Drive_sub_18
00AD: set_car 7@ max_speed_to 5.0
01EB: set_car_density_to 0.0
0006: 15@ = 8 // integer values
0007: 11@ = -1299.78 // floating-point values
0007: 12@ = -565.30 // floating-point values
0007: 13@ = 13.76 // floating-point values
0175: set_car 7@ z_angle_to 0.0
000A: 16@ += 0 // integer values
0007: 17@ = 100.0 // floating-point values
0007: 18@ = 20.0 // floating-point values
04e0: car 7@ abandon_path_radius 250
jump @Drive_sub_100

:Drive_sub_18
if
0039: 15@ == 8 // integer values
jf @Drive_sub_109
if
01AF: car 7@ 0 ()near_point 11@ 12@ 13@ radius 25.2 25.2 5.0
jf @Drive_sub_109
00AD: set_car 7@ max_speed_to 0.0
0006: 15@ = 1 // integer values
000A: 16@ += 1 // integer values
0007: 11@ = -1181.78 // floating-point values
0007: 12@ = -331.30 // floating-point values
0007: 13@ = 13.76 // floating-point values
0175: set_car 7@ z_angle_to 1.0
0007: 17@ = 100.0 // floating-point values
0007: 18@ = 20.0 // floating-point values
04e0: car 7@ abandon_path_radius 250
00AE: unknown_set_car 7@ to_ignore_traffic_lights 2

if
0039: 16@ == 2 // integer values
jf @Drive_sub_100
00BC: text_highpriority 'BJ_LOSE' 5000 ms 1
jump @Drive_sub_100

:Drive_sub_99
if
0039: 19@ == 0 // integer values
jf @Drive_sub_109
00AD: set_car 7@ max_speed_to 0.0
05CB: actor_goto_and_enter_car 9@ 7@ 5000
0006: 19@ = 1 // integer values
jump @Drive_sub_109

:Drive_sub_100
00A7: car 7@ drive_to 11@ 12@ 13@
00AD: set_car 7@ max_speed_to 17@
03F0: text_draw_toggle 0
0006: 33@ = 0 // integer values
jump @Drive_sub_109

:Drive_sub_102
if
01F3: car 7@ airborne
jf @Drive_sub_103
0007: 18@ = 0.0 // floating-point values
00A7: car 7@ drive_to 11@ 12@ 13@
04BA: set_car 7@ speed_instantly 18@
00AD: set_car 7@ max_speed_to 17@
jump @Drive_sub_103

:Drive_sub_103
if
01AF: car 7@ 0 ()near_point 11@ 12@ 13@ radius 30.2 30.2 5.0
jf @Drive_sub_104
jump @Drive_sub_105

:Drive_sub_104
02E3: 20@ = car 7@ speed
if
81F3: NOT car 7@ airborne
jf @Drive_sub_106
if and
0021: 20@ > 30.0 // floating-point values
0019: 33@ > 700 // integer values
jf @Drive_sub_105
04BA: set_car 7@ speed_instantly 50.0

:Drive_sub_105
if
0019: 33@ > 2000 // integer values
jf @Drive_sub_109

:Drive_sub_106
0006: 33@ = 0 // integer values

:Drive_sub_109
0051: return
----------------------------------------------------------------------------
SF机场环行程序V2
这段程序和上面的是一样的,不过用到了07E7: AS_assign_scmpath_to_actor
{$CLEO .cs}
:scmpath_1
03A4: name_thread 'SCMP'

:scmpath_3
0001: wait 0 ms
if
0256: player $PLAYER_CHAR defined
jf @scmpath_3
077E: 0@ = active_interior
if and
0038: 0@ == 0 // integer values
0AB0: key_pressed 8//----------------------------------------Backspace
jf @scmpath_3
016A: fade 0 () 250 ms
0001: wait 250 ms
01B4: set_player $PLAYER_CHAR frozen_state 0 (frozen)
0362: remove_actor $PLAYER_ACTOR from_car_and_place_at -1338.5 -408.1 14.1
0173: set_actor $PLAYER_ACTOR z_angle_to 90.8
0001: wait 500 ms
0247: request_model #NRG500
0247: request_model #MAFFA

:scmpath_5
0001: wait 0 ms
if and
0248: model #NRG500 available
0248: model #MAFFA available
jf @scmpath_5
00A5: 1@ = create_car #NRG500 at -1333.5 -408.1 14.1
0175: set_car 1@ z_angle_to 280.0
0224: set_car 1@ health_to 2000
00A5: 7@ = create_car #NRG500 at -1354.5 -419.1 14.1
0175: set_car 7@ z_angle_to 280.0
0224: set_car 7@ health_to 2000
020A: set_car 7@ door_status_to 4
02AC: set_car 7@ immunities 1 1 1 1 1
01EC: make_car 7@ very_heavy 1
0129: 9@ = create_actor 24 #MAFFA in_car 7@ driverseat
0223: set_actor 9@ health_to 3000
04E4: unknown_refresh_game_renderer_at -1333.5 -408.1
03CB: set_camera -1333.5 -408.1 14.1
029B: 23@ = init_object 1655 at -1576.02 -202.34 13.76
0177: set_object 23@ z_angle_to 270.0
01C7: remove_object_from_mission_cleanup_list 23@
0382: set_object 23@ collision_detection 1
029B: 24@ = init_object 1655 at -1597.9 -506.5 21.7
0177: set_object 24@ z_angle_to 270.0
01C7: remove_object_from_mission_cleanup_list 24@
0382: set_object 24@ collision_detection 1
029B: 25@ = init_object 1655 at -1375.9 -581.5 13.69
0177: set_object 25@ z_angle_to 270.0
01C7: remove_object_from_mission_cleanup_list 25@
0382: set_object 25@ collision_detection 1
029B: 26@ = init_object 1655 at -1374.9 -585.5 13.69
0177: set_object 26@ z_angle_to 270.0
01C7: remove_object_from_mission_cleanup_list 26@

0382: set_object 26@ collision_detection 1
0177: set_object 23@ z_angle_to 135.0
0177: set_object 24@ z_angle_to 225.0
0177: set_object 25@ z_angle_to 280.0
0177: set_object 26@ z_angle_to 280.0
0186: 29@ = create_marker_above_car 7@
07E0: set_marker 29@ type_to 1

0249: release_model #NRG500
0249: release_model #MAFFA
04e0: car 7@ abandon_path_radius 200
00AD: set_car 7@ max_speed_to 100.0
04BA: set_car 7@ speed_instantly 30.0
00AF: set_car 7@ driver_behaviour_to 1
00AE: unknown_set_car 7@ to_ignore_traffic_lights 2
0001: wait 250 ms
036A: put_actor $PLAYER_ACTOR in_car 1@
0001: wait 250 ms
016A: fade 1 () 1000 ms
0001: wait 1000 ms
0373: set_camera_directly_behind_player
02EB: restore_camera_with_jumpcut
01B4: set_player $PLAYER_CHAR frozen_state 1 (unfrozen)
0006: 15@ = 0 // integer values
0006: 16@ = 0 // integer values
0006: 20@ = 20000 // floating-point values
0006: 19@ = 0 // integer values
0007: 11@ = -1320.48 // floating-point values
0007: 12@ = -407.1 // floating-point values
0007: 13@ = 13.76 // floating-point values
00A7: car 7@ drive_to 11@ 12@ 13@
00AD: set_car 7@ max_speed_to 1.0
04e0: car 7@ abandon_path_radius 250
08C6: set_actor 9@ stay_on_bike 1

:scmpath_7
0001: wait 0 ms
if
0256: player $PLAYER_CHAR defined
jf @scmpath_7

0050: gosub @scmpath_sub_3

if and
8119: NOT car 1@ wrecked
8119: NOT car 7@ wrecked
8118: NOT actor 9@ dead
jf @scmpath_7
if
00FE: actor $PLAYER_ACTOR 0 ()near_point -1333.5 -408.1 14.1 radius 650.5 650.5 50.5
jf @scmpath_12
jump @scmpath_7

:scmpath_12
0164: disable_marker 29@
01C3: remove_references_to_car 1@ // Like turning a car into any random car
01C3: remove_references_to_car 7@ // Like turning a car into any random car
01C2: remove_references_to_actor 9@ // Like turning an actor into a random pedestrian
0108: destroy_object 23@
0108: destroy_object 24@
0108: destroy_object 25@
0108: destroy_object 26@
jump @scmpath_3

:scmpath_sub_3
if
8119: NOT car 7@ wrecked
jf @scmpath_sub_109
if
00DB: actor 9@ in_car 7@
jf @scmpath_sub_99
if
0039: 19@ == 1 // integer values
jf @scmpath_sub_10
0006: 19@ = 0 // integer values
jump @scmpath_sub_100

:scmpath_sub_10
if
0039: 15@ == 0 // integer values
jf @scmpath_sub_11
if
01AF: car 7@ 0 ()near_point 11@ 12@ 13@ radius 5.2 5.2 5.0
jf @scmpath_sub_11
0006: 15@ = 1 // integer values
05D6: clear_scmpath
0007: 11@ = -1181.78 // floating-point values
0007: 12@ = -331.30 // floating-point values
0007: 13@ = 13.76 // floating-point values
000A: 16@ += 0 // integer values
0007: 17@ = 100.0 // floating-point values
0007: 18@ = 20.0 // floating-point values
05D7: add_point_to_scmpath 11@ 12@ 13@
jump @scmpath_sub_100

:scmpath_sub_11
if
0039: 15@ == 1 // integer values
jf @scmpath_sub_12
if
01AF: car 7@ 0 ()near_point 11@ 12@ 13@ radius 15.2 15.2 5.0
jf @scmpath_sub_12
00AD: set_car 7@ max_speed_to 10.0
0006: 15@ = 2 // integer values
05D6: clear_scmpath
0007: 11@ = -1282.1 // floating-point values
0007: 12@ = -159.3 // floating-point values
0007: 13@ = 13.76 // floating-point values
000A: 16@ += 0 // integer values
0007: 17@ = 100.0 // floating-point values
0007: 18@ = 20.0 // floating-point values
05D7: add_point_to_scmpath 11@ 12@ 13@
jump @scmpath_sub_100

:scmpath_sub_12
if
0039: 15@ == 2 // integer values
jf @scmpath_sub_13
if
01AF: car 7@ 0 ()near_point 11@ 12@ 13@ radius 15.2 15.2 5.0
jf @scmpath_sub_13
00AD: set_car 7@ max_speed_to 25.0
0006: 15@ = 3 // integer values
05D6: clear_scmpath
0007: 11@ = -1498.78 // floating-point values
0007: 12@ = -138.30 // floating-point values
0007: 13@ = 13.76 // floating-point values
000A: 16@ += 0 // integer values
0007: 17@ = 100.0 // floating-point values
0007: 18@ = 20.0 // floating-point values
05D7: add_point_to_scmpath 11@ 12@ 13@
jump @scmpath_sub_100

:scmpath_sub_13
if
0039: 15@ == 3 // integer values
jf @scmpath_sub_14
if
01AF: car 7@ 0 ()near_point 11@ 12@ 13@ radius 8.2 8.2 5.0
jf @scmpath_sub_14
00AD: set_car 7@ max_speed_to 25.0
0006: 15@ = 4 // integer values
05D6: clear_scmpath
0007: 11@ = -1576.78 // floating-point values
0007: 12@ = -202.30 // floating-point values
0007: 13@ = 13.76 // floating-point values
000A: 16@ += 0 // integer values
0007: 17@ = 100.0 // floating-point values
0007: 18@ = 20.0 // floating-point values
05D7: add_point_to_scmpath 11@ 12@ 13@
jump @scmpath_sub_100

:scmpath_sub_14
if
0039: 15@ == 4 // integer values
jf @scmpath_sub_15
if
01AF: car 7@ 0 ()near_point 11@ 12@ 13@ radius 5.2 5.2 5.0
jf @scmpath_sub_15
0006: 15@ = 5 // integer values
05D6: clear_scmpath
0007: 11@ = -1694.78 // floating-point values
0007: 12@ = -352.30 // floating-point values
0007: 13@ = 13.9 // floating-point values
000A: 16@ += 0 // integer values
0007: 17@ = 100.0 // floating-point values
0007: 18@ = 20.0 // floating-point values
05D7: add_point_to_scmpath 11@ 12@ 13@
jump @scmpath_sub_100

:scmpath_sub_15
if
0039: 15@ == 5 // integer values
jf @scmpath_sub_16
if
01AF: car 7@ 0 ()near_point 11@ 12@ 13@ radius 15.2 15.2 5.0
jf @scmpath_sub_16
00AD: set_car 7@ max_speed_to 10.0
0006: 15@ = 6 // integer values
05D6: clear_scmpath
0007: 11@ = -1691.78 // floating-point values
0007: 12@ = -409.30 // floating-point values
0007: 13@ = 13.9 // floating-point values
000A: 16@ += 0 // integer values
0007: 17@ = 40.0 // floating-point values
0007: 18@ = 10.0 // floating-point values
05D7: add_point_to_scmpath 11@ 12@ 13@
00AE: unknown_set_car 7@ to_ignore_traffic_lights 2
jump @scmpath_sub_100

:scmpath_sub_16
if
0039: 15@ == 6 // integer values
jf @scmpath_sub_17
if
01AF: car 7@ 0 ()near_point 11@ 12@ 13@ radius 8.2 8.2 5.0
jf @scmpath_sub_17
00AD: set_car 7@ max_speed_to 0.0
0006: 15@ = 7 // integer values
05D6: clear_scmpath
0007: 11@ = -1519.78 // floating-point values
0007: 12@ = -580.30 // floating-point values
0007: 13@ = 13.76 // floating-point values
000A: 16@ += 0 // integer values
0007: 17@ = 100.0 // floating-point values
0007: 18@ = 0.0 // floating-point values
05D7: add_point_to_scmpath 11@ 12@ 13@
00AE: unknown_set_car 7@ to_ignore_traffic_lights 2
jump @scmpath_sub_100

:scmpath_sub_17
if
0039: 15@ == 7 // integer values
jf @scmpath_sub_18
if
01AF: car 7@ 0 ()near_point 11@ 12@ 13@ radius 15.2 15.2 5.0
jf @scmpath_sub_18
00AD: set_car 7@ max_speed_to 5.0
01EB: set_car_density_to 0.0
0006: 15@ = 8 // integer values
05D6: clear_scmpath
0007: 11@ = -1299.78 // floating-point values
0007: 12@ = -565.30 // floating-point values
0007: 13@ = 13.76 // floating-point values
000A: 16@ += 0 // integer values
0007: 17@ = 100.0 // floating-point values
0007: 18@ = 20.0 // floating-point values
05D7: add_point_to_scmpath 11@ 12@ 13@
jump @scmpath_sub_100

:scmpath_sub_18
if
0039: 15@ == 8 // integer values
jf @scmpath_sub_109
if
01AF: car 7@ 0 ()near_point 11@ 12@ 13@ radius 25.2 25.2 5.0
jf @scmpath_sub_109
00AD: set_car 7@ max_speed_to 0.0
0006: 15@ = 1 // integer values
000A: 16@ += 1 // integer values
05D6: clear_scmpath
0007: 11@ = -1181.78 // floating-point values
0007: 12@ = -331.30 // floating-point values
0007: 13@ = 13.76 // floating-point values
0007: 17@ = 100.0 // floating-point values
0007: 18@ = 20.0 // floating-point values
05D7: add_point_to_scmpath 11@ 12@ 13@

if
0039: 16@ == 2 // integer values
jf @scmpath_sub_100
00BC: text_highpriority 'BJ_LOSE' 5000 ms 1
jump @scmpath_sub_100

:scmpath_sub_99
if
0039: 19@ == 0 // integer values
jf @scmpath_sub_109
00AD: set_car 7@ max_speed_to 0.0
05CB: actor_goto_and_enter_car 9@ 7@ 5000
0006: 19@ = 1 // integer values
jump @scmpath_sub_109

:scmpath_sub_100
07E7: AS_assign_scmpath_to_actor 9@ in_car 7@ speed 17@ flags 2 0 3
03F0: text_draw_toggle 0
0006: 33@ = 0 // integer values
jump @scmpath_sub_109

:scmpath_sub_102
if
01F3: car 7@ airborne
jf @scmpath_sub_103
0007: 18@ = 0.0 // floating-point values
04BA: set_car 7@ speed_instantly 18@
07E7: AS_assign_scmpath_to_actor 9@ in_car 7@ speed 17@ flags 2 0 3
jump @scmpath_sub_103

:scmpath_sub_103
if
01AF: car 7@ 0 ()near_point 11@ 12@ 13@ radius 30.2 30.2 5.0
jf @scmpath_sub_104
jump @scmpath_sub_105

:scmpath_sub_104
02E3: 20@ = car 7@ speed
if
81F3: NOT car 7@ airborne
jf @scmpath_sub_106
if and
0021: 20@ > 30.0 // floating-point values
0019: 33@ > 700 // integer values
jf @scmpath_sub_105
04BA: set_car 7@ speed_instantly 50.0

:scmpath_sub_105
if
0019: 33@ > 2000 // integer values
jf @scmpath_sub_109

:scmpath_sub_106
0006: 33@ = 0 // integer values

:scmpath_sub_109
0051: return

为主的祥助 发表于 2012-4-7 10:39:44

本帖最后由 kwanz 于 2012-4-13 19:23 编辑

用Carrec Path指定车辆行驶路径

用Seemann的carrec.cs记录路径 http://cleo.sannybuilder.com/
详见 http://www.gtaforums.com/index.php?showtopic=297295

然后它会在GTASA\data\paths中建立path

把它改名为carrec899.rrr并导入carrec.img
然后就可以用下面的程序指定路径
{$CLEO .cs}
:DrvCarrec_1
03A4: name_thread 'DRVCARC'

:DRVCARC_11
0001: wait 0 ms
00D6: if
0256: player $PLAYER_CHAR defined
004D: jump_if_false @DRVCARC_11
00D6: if and
0AB0: key_pressed 57
00DF: actor $PLAYER_ACTOR driving
004D: jump_if_false @DRVCARC_11
03C0: 0@ = actor $PLAYER_ACTOR car
0A30: repair_car 0@
0224: set_car 0@ health_to 1000
0006: 8@ = 899
07C0: load_path 8@

:DRVCARC_85
0001: wait 0 ms
00D6: if
07C1: path 8@ available
004D: jump_if_false @DRVCARC_85
00D6: if
8119: not car 0@ wrecked
004D: jump_if_false @DRVCARC_218
0001: wait 500 ms
05EB: assign_car 0@ to_path 8@

:DRVCARC_148
0001: wait 0 ms
00D6: if
0256: player $PLAYER_CHAR defined
004D: jump_if_false @DRVCARC_218
00D6: if or
0AB0: key_pressed 48
0119: car 0@ wrecked
004D: jump_if_false @DRVCARC_195
0002: jump @DRVCARC_218

:DRVCARC_195
00D6: if
00DF: actor $PLAYER_ACTOR driving
004D: jump_if_false @DRVCARC_218
0002: jump @DRVCARC_148

:DRVCARC_218
0001: wait 0 ms
00D6: if
0256: player $PLAYER_CHAR defined
004D: jump_if_false @DRVCARC_218
0373: set_camera_directly_behind_player
02EB: restore_camera_with_jumpcut
05EC: release_car 0@ from_path
0873: release_path 8@
01C3: remove_references_to_car 0@ // 设为随机车辆
0001: wait 1000 ms
0002: jump @DRVCARC_11

为主的祥助 发表于 2012-4-7 10:40:01

本帖最后由 kwanz 于 2012-4-13 19:24 编辑

在Carrec path中使用镜头

只有015F和0159合用可以实现镜头自动跟踪移动物体
但在SA里我们在SA中已有足够多的代码来实现各种效果。
我们可以把车辆的位置读入变量,然后把变量赋给标准的镜头定位函数来调视角
使用parked_car_generator的车辆位置标志不能用于车辆相关的opcode,因为那不是一辆车,只是一个生成器,但我们可以直接把坐标用于镜头定位函数

下面的代码会刷出一辆NRG500,按8让镜头跟随carrec899.rrr中定义的carrec路径
镜头指向固定的XYZ坐标点
(我在SF机场摆了一台Monster然后开摩托绕着它转,并在代码中直接利用了parked_car Monster的坐标)
//-init_parked_car_generator #MONSTER color -1 -1 1 alarm 0 door_lock 0 0 10000 at -1355.7821 -71.4736 14.1462 angle 86.0
0160: set_camera_point_at -1355.7821 -71.4736 14.1462 mode 2
{$CLEO .cs}
:CameraDrive_1
03A4: name_thread 'DRVCARC'

:CameraDrive_11
0001: wait 0 ms
00D6: if
0256: player $PLAYER_CHAR defined
004D: jump_if_false @CameraDrive_11
if
0AB0: key_pressed 56//----------- key 8
004D: jump_if_false @CameraDrive_11
0247: request_model #NRG500

:CameraDrive_13
0001: wait 0 ms
00D6: if 0
0248: model #NRG500 available
004D: jump_if_false @CameraDrive_13

00A5: 0@ = create_car #NRG500 at 0.0 0.0 100.0
0175: set_car 0@ z_angle_to 0.0
02AC: set_car 0@ immunities BP 1 FP 1 EP 1 CP 1 MP 1
0249: release_model #NRG500
0006: 8@ = 899
07C0: load_path 8@

:CameraDrive_17
0001: wait 0 ms
00D6: if
07C1: path 8@ available
004D: jump_if_false @CameraDrive_17
00D6: if
8119: not car 0@ wrecked
004D: jump_if_false @CameraDrive_50
0001: wait 500 ms
05EB: assign_car 0@ to_path 8@

:CameraDrive_21
0001: wait 0 ms
00D6: if
0256: player $PLAYER_CHAR defined
004D: jump_if_false @CameraDrive_50
00D6: if or
00E1: key_pressed 0 15//Enter/Exit
0119: car 0@ wrecked
004D: jump_if_false @CameraDrive_25
0002: jump @CameraDrive_50

:CameraDrive_25
0407: create_coordinate 11@ 12@ 13@ from_car 0@ with_offset 0.0 0.0 1.0
015F: set_camera_position 11@ 12@ 13@ rotation 0.0 0.0 0.0
//init_parked_car_generator #MONSTER at -1355.7821 -71.4736 14.1462
0160: set_camera_point_at -1355.7821 -71.4736 14.1462 mode 2
0002: jump @CameraDrive_21

:CameraDrive_50
0001: wait 0 ms
00D6: if
0256: player $PLAYER_CHAR defined
004D: jump_if_false @CameraDrive_50
0373: set_camera_directly_behind_player
02EB: restore_camera_with_jumpcut
05EC: release_car 0@ from_path
0873: release_path 8@
01C3: remove_references_to_car 0@ // Like turning a car into any random car
0001: wait 1000 ms
0002: jump @CameraDrive_11
从移动的车辆上查看移动的目标会稍微复杂一点,因为我们需要编程跟踪移动的目标,同时实现镜头在carrec path上的移动。
我把车辆行驶程序和镜头移动程序整在一起
下面的代码在Grove St刷出Infernus,车上有两个小弟,当玩家进圈时,程序再刷出一辆NRG500,行驶路径为carrect899.rrr的carrec path,镜头跟随并指向行驶的Infernus。
{$CLEO .cs}
:CarrecCamCarDrive_1
03A4: name_thread 'CRCMCDR'

:CarrecCamCarDrive_2
0001: wait 0 ms
if
0256: player $PLAYER_CHAR defined
004D: jump_if_false @CarrecCamCarDrive_2
if
00FE: actor $PLAYER_ACTOR 1 (in-sphere)near_point 2491.5 -1667.5 13.35 radius 1.0 1.0 1.0
004D: jump_if_false @CarrecCamCarDrive_2

0247: request_model #INFERNUS
0247: request_model #fam1
0247: request_model #fam2
0247: request_model #NRG500

:CarrecCamCarDrive_3
0001: wait 0 ms
if and
0248: model #INFERNUS available
0248: model #fam1 available
0248: model #fam2 available
0248: model #NRG500 available
004D: jump_if_false @CarrecCamCarDrive_3

00A5: 1@ = create_car #INFERNUS at 2487.5 -1660.5 13.35
0175: set_car 1@ z_angle_to 90.0
0129: 2@ = create_actor 8 #fam1 in_car 1@ driverseat
01C8: 3@ = create_actor 8 #fam2 in_car 1@ passenger_seat 0
0186: 4@ = create_marker_above_car 1@
07E0: set_marker 4@ type_to 1

00A5: 0@ = create_car #NRG500 at 0.0 0.0 100.0
0175: set_car 0@ z_angle_to 0.0
02AC: set_car 0@ immunities BP 1 FP 1 EP 1 CP 1 MP 1

0006: 8@ = 899
07C0: load_path 8@

:CarrecCamCarDrive_5
0001: wait 0 ms
00D6: if
07C1: path 8@ available
004D: jump_if_false @CarrecCamCarDrive_5
00D6: if
8119: not car 0@ wrecked
004D: jump_if_false @CarrecCamCarDrive_50
0001: wait 500 ms
05EB: assign_car 0@ to_path 8@

//////////////////// drive-to块开始

0615: define_action_sequences 5@
05D1: AS_actor -1 drive_car 1@ to 2353.1528 -1658.6493 13.384 speed 20.0 0 0 5
05D1: AS_actor -1 drive_car 1@ to 2431.7739 -1674.7444 13.6643 speed 20.0 0 0 5
05D1: AS_actor -1 drive_car 1@ to 2431.5864 -1628.0818 13.698 speed 20.0 2 0 5
0616: define_action_sequences_end 5@
0618: assign_actor 2@ to_action_sequences 5@
061B: remove_references_to_AS_pack 5@

//////////////////// drive-to块结束

:CarrecCamCarDrive_13
0001: wait 0 ms
if
0256: player $PLAYER_CHAR defined
004D: jump_if_false @CarrecCamCarDrive_13

//////////////////// camera块 必须循环
0407: create_coordinate 11@ 12@ 13@ from_car 0@ with_offset 0.0 0.0 1.5
015F: set_camera_position 11@ 12@ 13@ rotation 0.0 0.0 0.0
0407: create_coordinate 14@ 15@ 16@ from_car 1@ with_offset 0.0 0.0 1.0
0160: set_camera_point_at 14@ 15@ 16@ mode 2
//////////////////// camera块 必须循环

if or
00E1: key_pressed 0 15//Enter/Exit
0119: car 0@ wrecked
0119: car 1@ wrecked
01F4: car 1@ flipped
8202: not actor $PLAYER_ACTOR near_car 1@ radius 500.0 500.0 flag 0
004D: jump_if_false @CarrecCamCarDrive_13

:CarrecCamCarDrive_50
0001: wait 0 ms
00D6: if
0256: player $PLAYER_CHAR defined
004D: jump_if_false @CarrecCamCarDrive_50
0373: set_camera_directly_behind_player
02EB: restore_camera_with_jumpcut
05EC: release_car 0@ from_path
0873: release_path 8@
01C3: remove_references_to_car 0@ // 设为随机车辆
01C3: remove_references_to_car 1@ // 设为随机车辆
01C2: remove_references_to_actor 2@ // 设为随机行人
01C2: remove_references_to_actor 3@ // 设为随机行人
0164: disable_marker 4@
0249: release_model #INFERNUS
0249: release_model #fam1
0249: release_model #fam2
0249: release_model #NRG500
0001: wait 1000 ms
0002: jump @CarrecCamCarDrive_2

为主的祥助 发表于 2012-4-7 10:55:24

本帖最后由 kwanz 于 2012-4-13 19:26 编辑

----------------------------------------
显示粒子特效的特殊opcode
----------------------------------------
有几个特殊的opcode支持直接调用显示预定义的粒子特效,不需要特别的参数。特效只能显示很短的一段时间,要看到效果必须用到循环。

1.
08EB: create_sparks_at 1@ 2@ 3@ velocity_direction 0.0 5.0 20.0 density 100
火花(spark)是仅在effects.fxp中有效的附加fxs数据(sub-fxs-data)
我猜08EB的火花是exe中直接编程实现的,没有用到材质
08EB带有7个参数
参数1,2,3=x,y,z 浮点型,生成火花的绝对坐标
参数4,5,6=x,y,z浮点型,火花溅射方向的相对坐标
参数7=密度,整型
增加方向坐标可以增大火花的范围

下面的代码能生成最大密度的火花
按退格键在玩家面前产生火花{$CLEO .cs}
:Particle_Sparks
03A4: name_thread 'PRTSPRK'

:PRTSPRK_01
0001: wait 0 ms
if
0256: player $PLAYER_CHAR defined
004D: jump_if_false @PRTSPRK_01
if
0AB0: key_pressed 8//-----------------------按退格
004D: jump_if_false @PRTSPRK_01
04C4: create_coordinate 1@ 2@ 3@ from_actor $PLAYER_ACTOR offset 0.0 3.5 0.3
08EB: create_sparks_at 1@ 2@ 3@ velocity_direction 0.0 5.0 20.0 density 100
jump @PRTSPRK_012.
058A: create_gun_flash_from 1@ 2@ 3@ to 11@ 12@ 13@
058A显示开枪的弹道效果,需要生成位置和方向的绝对坐标
058A带6个参数
参数1,2,3=x,y,z浮点型,生成位置的绝对坐标
参数4,5,6=x,y,z浮点型,方向的绝对坐标

下面的代码显示出和玩家朝向相同的弹道效果
按退格键在玩家面前生成弹道{$CLEO .cs}
:Particle_GunFlash
03A4: name_thread 'PRTGFLS'

:PRTGFLS_01
0001: wait 0 ms
if
0256: player $PLAYER_CHAR defined
004D: jump_if_false @PRTGFLS_01
if
0AB0: key_pressed 8//-----------------------按退格
004D: jump_if_false @PRTGFLS_01
04C4: create_coordinate 1@ 2@ 3@ from_actor $PLAYER_ACTOR offset 0.0 1.5 0.3
04C4: create_coordinate 11@ 12@ 13@ from_actor $PLAYER_ACTOR offset 0.0 10.5 0.3
058A: create_gun_flash_from 1@ 2@ 3@ to 11@ 12@ 13@
jump @PRTGFLS_013.
09B8: create_blood_gush_at 1@ 2@ 3@ with_offset 0.0 3.0 0.0 density 80 on_actor $PLAYER_ACTOR
09B8显示prt_blood.fxs的掉血效果,但跟PLAYMODE: 2参数没有关系
它会显示为红色,但如果直接调opcode用prt_blood效果的话,是无色的
09B8带8个参数
参数1,2,3=x,y,z浮点型,生成位置的绝对坐标
参数4,5,6=x,y,z浮点型,血液溅射方向的相对坐标;但这个偏移量取的是单位圆上的绝对方向
参数7=密度
参数8=启用效果的人物对象变量

按退格键,玩家身上开始掉血{$CLEO .cs}
:Particle_Blood_Gush
03A4: name_thread 'PTBLOOD'

:PTBLOOD_01
0001: wait 0 ms
if
0256: player $PLAYER_CHAR defined
004D: jump_if_false @PTBLOOD_01
if
0AB0: key_pressed 8//-----------------------press Backspace
004D: jump_if_false @PTBLOOD_01
04C4: create_coordinate 1@ 2@ 3@ from_actor $PLAYER_ACTOR offset 0.2 0.0 0.5
09B8: create_blood_gush_at 1@ 2@ 3@ with_offset 0.0 3.0 3.0 density 80 on_actor $PLAYER_ACTOR
jump @PTBLOOD_014.
04D5: create_corona_at 1@ 2@ 3@ radius 1.5 type 2 flare 1 RGB 247 206 12
04D5用GTASA\models\particle.txd中存储的材质,显示出一个半透明的发光源物体
opcode 04D5带9个参数
参数1,2,3=x,y,z浮点型,生成位置的绝对坐标
参数4=大小,浮点型
参数5=类型,整型,更换材质
参数6=显示发光效果,布尔型0/1
参数7,8,9=整型,RGB颜色值

按退格键在玩家面前显示4种不同的光圈{$CLEO .cs}
:Corona_1
03A4: name_thread 'CORA'

:Corona_3
0001: wait 0 ms
if
0256: player $PLAYER_CHAR defined
004D: jump_if_false @Corona_3
00D6: if
0AB0: key_pressed 8//-----------------------按退格
004D: jump_if_false @Corona_3
04C4: create_coordinate 1@ 2@ 3@ from_actor $PLAYER_ACTOR offset -5.0 7.0 2.2
04D5: create_corona_at 1@ 2@ 3@ radius 1.5 type 1 flare 1 RGB 150 0 255
04C4: create_coordinate 4@ 5@ 6@ from_actor $PLAYER_ACTOR offset -2.0 7.0 3.2
04D5: create_corona_at 4@ 5@ 6@ radius 1.5 type 2 flare 1 RGB 247 206 12
04C4: create_coordinate 7@ 8@ 9@ from_actor $PLAYER_ACTOR offset 3.0 7.0 5.2
04D5: create_corona_at 7@ 8@ 9@ radius 1.5 type 3 flare 0 RGB 255 7 7
04C4: create_coordinate 10@ 11@ 12@ from_actor $PLAYER_ACTOR offset 6.0 7.0 3.2
04D5: create_corona_at 10@ 11@ 12@ radius 1.5 type 4 flare 0 RGB 3 3 255
0002: jump @Corona_35.
016F: create_particle 1 rotation_factor 0.0 size 180.0 intensity 250 flags 0 0 0 at 1@ 2@ 3@
opcode 016F: 在地面上显示阴影
opcode 016F: 带10个参数
参数1 =阴影强度 1 = 深阴影 / 2 = 浅阴影
参数2 =旋转因子(未知),浮点型
参数 3 =大小,浮点型
参数4 = 强度, 浮点型
参数5,6,7 =标志位变量 (未测试)
参数 8,9,10 = x,y,z浮点型, 生成位置的绝对坐标

按退格键在地面上显示阴影{$CLEO .cs}
:Particle_Shadow
03A4: name_thread 'PTSHAD'

:PTSHAD_01
0001: wait 0 ms
if
0256: player $PLAYER_CHAR defined
004D: jump_if_false @PTSHAD_01
if
0AB0: key_pressed 8//-----------------------按退格
004D: jump_if_false @PTSHAD_01
04C4: create_coordinate 1@ 2@ 3@ from_actor $PLAYER_ACTOR offset 0.0 0.0 0.0
016F: create_particle 1 rotation_factor 0.0 size 180.0 intensity 250 flags 0 0 0 at 1@ 2@ 3@
jump @PTSHAD_016.
095C: create_smoke_at 1@ 2@ 3@ velocity 0.0 1.0 7.0 RGBA 0.0 0.0 0.0 1.0 size 0.1 last_factor 0.02//black
Opcode 095C 显示prt_smoke_huge.fxs中的烟雾效果,但与PLAYMODE: 2参数无关

095C带有12个参数,全为浮点型
参数1,2,3 = x,y,z 生成位置的绝对坐标
参数4,5,6 = x,y,z 烟雾蔓延方向的相对坐标
参数7,8,9,10 = 颜色值,R-G-B-不透明度
参数11 = 初始大小
参数12 =结束大小

下面的代码显示8股烟雾,不同颜色、大小、移动速度(较大的方向坐标能让烟雾移动更快)
按退格键产生烟雾
opcode 04C4: 获得玩家前3.5个单位的坐标
opcode 095C: 生成烟雾{$CLEO .cs}
:Particle_Smoke
03A4: name_thread 'PRTSMOK'

:PRTSMOKE_01
0001: wait 0 ms
if
0256: player $PLAYER_CHAR defined
004D: jump_if_false @PRTSMOKE_01
if
0AB0: key_pressed 8//-----------------------按退格
004D: jump_if_false @PRTSMOKE_01
04C4: create_coordinate 1@ 2@ 3@ from_actor $PLAYER_ACTOR offset 0.0 3.5 0.3
33@ = 0

:PRTSMOKE_02_black
wait 0
if
3000 > 33@
jf @PRTSMOKE_03_blue
095C: create_smoke_at 1@ 2@ 3@ velocity 0.0 1.0 7.0 RGBA 0.0 0.0 0.0 1.0 size 0.1 last_factor 0.02//black
jump @PRTSMOKE_02_black

:PRTSMOKE_03_blue
wait 0
if
6000 > 33@
jf @PRTSMOKE_04_green
095C: create_smoke_at 1@ 2@ 3@ velocity 0.0 0.0 50.0 RGBA 0.0 0.0 1.0 1.0 size 0.5 last_factor 0.02//blue
jump @PRTSMOKE_03_blue

:PRTSMOKE_04_green
wait 0
if
9000 > 33@
jf @PRTSMOKE_05_red
095C: create_smoke_at 1@ 2@ 3@ velocity 0.0 0.0 10.0 RGBA 0.0 1.0 0.0 1.0 size 1.0 last_factor 0.02//green
jump @PRTSMOKE_04_green

:PRTSMOKE_05_red
wait 0
if
12000 > 33@
jf @PRTSMOKE_06_yellow
095C: create_smoke_at 1@ 2@ 3@ velocity 0.0 0.0 1.0 RGBA 1.0 0.0 0.0 1.0 size 5.5 last_factor 0.02//red
jump @PRTSMOKE_05_red

:PRTSMOKE_06_yellow
wait 0
if
15000 > 33@
jf @PRTSMOKE_07_turquoise
095C: create_smoke_at 1@ 2@ 3@ velocity 0.0 0.0 20.0 RGBA 1.0 1.0 0.0 1.0 size 9.5 last_factor 0.02//yellow
jump @PRTSMOKE_06_yellow

:PRTSMOKE_07_turquoise
wait 0
if
18000 > 33@
jf @PRTSMOKE_08_pink
095C: create_smoke_at 1@ 2@ 3@ velocity 0.0 0.0 20.0 RGBA 0.0 1.0 1.0 1.0 size 0.5 last_factor 0.02//turquoise
jump @PRTSMOKE_07_turquoise

:PRTSMOKE_08_pink
wait 0
if
21000 > 33@
jf @PRTSMOKE_09_white
095C: create_smoke_at 1@ 2@ 3@ velocity 0.0 0.0 20.0 RGBA 1.0 0.0 1.0 1.0 size 0.5 last_factor 0.02//pink
jump @PRTSMOKE_08_pink

:PRTSMOKE_09_white
wait 0
if
24000 > 33@
jf @PRTSMOKE_01
095C: create_smoke_at 1@ 2@ 3@ velocity 0.0 0.0 20.0 RGBA 1.0 1.0 1.0 1.0 size 0.5 last_factor 0.02//white
jump @PRTSMOKE_09_white相关主题:灯光和阴影

为主的祥助 发表于 2012-4-7 10:55:55

本帖最后由 kwanz 于 2012-4-12 15:30 编辑

灯光的创建

GTASA中,灯光应符合三条事实:
1. 存在光源
2. 它带有光圈、光柱或类似的材质效果
3. 它能照亮环境

据我所知,满足这三条事实的灯光包括:
-车头灯:可以通过设定模型编辑器中的车灯对象来修改
-警灯:同上,但仅用于警车和其他紧急车辆
-火焰:通过创建火焰来实现,但使用粒子效果创建火焰并不会照亮环境
-爆炸:通过创建爆炸来实现,但使用粒子效果创建爆炸并不会照亮环境
-某些街灯
-交通灯

以上的事实3,照亮环境,是灯光效果最吸引人之处
只要试一下截个车辆截图你就会发现,显示效果取决于车辆的朝向和镜头的倾角。别的车的车灯会照亮你的车子,街灯和交通灯亦然。显示效果就像是你提着一盏灯站在后院里,同时受到路上的街车影响一样。

若要用地图修改的方式编辑灯光,我所知有两种方法
用MaxScript导出SA中的灯光和粒子效果
这些灯光对人物也有效,然而在我的测试中并不满足事实3,即照亮环境。
用3ds max设置带颜色的模型预照明 (prelighting)
这种方法可以充分地照亮模型,但是环境照明效果有限。

关于在脚本中调effects.fxp的效果,详情可参阅教程CLEO Script Tutorial>>Particle Effects
经测试这样的灯光都不满足事实3

09E5: create_flash_light 有照亮除地面外的环境的效果,但是它不具备事实1和2的性质,无光源,无光柱

以下代码演示了按9键照亮人物和环境的效果
{$CLEO .cs}
:Flash_Light_Illumination
thread 'FLHILLU'

:FLHILLU_11
wait 0
if
0AB0: key_pressed 57// key 9
jf @FLHILLU_11

:FLHILLU_46
wait 0
if
Player.Defined($PLAYER_CHAR)
jf @FLHILLU_46
if
0AB0: key_pressed 57// key 9
jf @FLHILLU_141
04C4: store_coords_to 1@ 2@ 3@ from_actor $PLAYER_ACTOR with_offset 0.0 0.0 1.0
09E5: create_flash_light_at 1@ 2@ 3@ RGB_mask 255 255 255 radius 200.0
jump @FLHILLU_46

:FLHILLU_141
wait 0
if
Player.Defined($PLAYER_CHAR)
jf @FLHILLU_141
04C4: store_coords_to 1@ 2@ 3@ from_actor $PLAYER_ACTOR with_offset 0.0 0.0 1.0
09E5: create_flash_light_at 1@ 2@ 3@ RGB_mask 255 255 255 radius 200.0
if
0AB0: key_pressed 57// key 9
jf @FLHILLU_141

:FLHILLU_229
wait 0
if
0AB0: key_pressed 57// key 9
jf @FLHILLU_11
jump @FLHILLU_229
Opcode create_searchlight会照亮地面并显示白色的光柱
以下代码能在8键按下时在玩家上方创建探照灯光
{$CLEO .cs}
:WhiteSearchLightLamp
thread 'WSLAMP'

:WhitSrchLght_11
wait 0
if
0256: player $PLAYER_CHAR defined
jf @WhitSrchLght_11
if
0AB0: key_pressed 56// 8 key
jf @WhitSrchLght_11
04C4: store_coords_to 1@ 2@ 3@ from_actor $PLAYER_ACTOR with_offset 0.0 0.0 70.0
04C4: store_coords_to 4@ 5@ 6@ from_actor $PLAYER_ACTOR with_offset 0.0 0.0 -0.5
06B1: 10@ = create_searchlight_at 1@ 2@ 3@ radius 5.0 target 4@ 5@ 6@ radius 71.0
06B6: set_searchlight 10@ follow_actor $PLAYER_ACTOR speed 1.2
wait 1000

:WhitSrchLght_46
wait 0
if
0256: player $PLAYER_CHAR defined
jf @WhitSrchLght_47
if
0AB0: key_pressed 56// 8 key
jf @WhitSrchLght_46

:WhitSrchLght_47
06B2: destroy_searchlight 10@
wait 1000
jump @WhitSrchLght_11

________
阴影的创建
________
016F: create_particle 1 在地面上创建阴影
以下的代码当退格键按住时在玩家下方创建阴影

{$CLEO .cs}
:Particle_Shadow
03A4: name_thread 'PTSHAD'

:PTSHAD_01
0001: wait 0 ms
if
0256: player $PLAYER_CHAR defined
004D: jump_if_false @PTSHAD_01
if
0AB0: key_pressed 8//-----------------------press Backspace
004D: jump_if_false @PTSHAD_01
04C4: create_coordinate 1@ 2@ 3@ from_actor $PLAYER_ACTOR offset 0.0 0.0 0.0
016F: create_particle 1 rotation_factor 0.0 size 180.0 intensity 250 flags 0 0 0 at 1@ 2@ 3@
jump @PTSHAD_01

___
引用 (hellya2011 @ Oct 3 2010, 01:03)
嗨zaz你能帮我么?我想把效果"sparycan"绑定到某武器上,按退格键时显示,应该怎么写?求助

opcode 0883: 把粒子特效绑定到人物骨骼
这可以让粒子出现在player_actors的手上:
066A: 0@ = attach_particle "spraycan" to_actor $PLAYER_ACTOR with_offset -0.301 -0.2 0.17 rotation -5.5 -3.5 0.0 flag 1
0883: attach_particle 0@ to_actor $PLAYER_ACTOR on_bone 26
064C: make_particle 0@ visible
你需要对不同的武器设定不同的偏移量。

下面的代码把"spraycan"绑定到人物手上,使用手枪或微冲按右键或瞄准键时适用
但是只有在用消声手枪和MP5的时候效果最好
别的武器的偏移量是不同的
当你用鼠标控制视角,在车子或者摩托上做driveby时也是好用的
{$CLEO .cs}
:Spraycan_at_ActorHand
03A4: name_thread 'SPRAYWP'

:SPRAYWP_01
0001: wait 0 ms
if
0256: player $PLAYER_CHAR defined
004D: jump_if_false @SPRAYWP_01
if or
00E1: key_pressed 0 17
00E1: key_pressed 0 6
0AB0: key_pressed 2// -- RMB
004D: jump_if_false @SPRAYWP_01
if
8965: not actor $PLAYER_ACTOR swimming
004D: jump_if_false @SPRAYWP_01
if or
02D8: actor $PLAYER_ACTOR current_weapon == 22
02D8: actor $PLAYER_ACTOR current_weapon == 23
02D8: actor $PLAYER_ACTOR current_weapon == 24
004D: jump_if_false @SPRAYWP_02
066A: 0@ = attach_particle "spraycan" to_actor $PLAYER_ACTOR with_offset -0.1 -0.22 0.13 rotation -1.5 -3.5 0.0 flag 1
0883: attach_particle 0@ to_actor $PLAYER_ACTOR mode 26
064C: make_particle 0@ visible
0002: jump @SPRAYWP_13

:SPRAYWP_02
if
02D8: actor $PLAYER_ACTOR current_weapon == 29
004D: jump_if_false @SPRAYWP_03
0002: jump @SPRAYWP_10

:SPRAYWP_03
if or
02D8: actor $PLAYER_ACTOR current_weapon == 32
02D8: actor $PLAYER_ACTOR current_weapon == 28
004D: jump_if_false @SPRAYWP_01
if or
00E1: key_pressed 0 17
0AB0: key_pressed 2// -- RMB
004D: jump_if_false @SPRAYWP_01
if
0449: actor $PLAYER_ACTOR in_a_car
004D: jump_if_false @SPRAYWP_01

:SPRAYWP_10
066A: 0@ = attach_particle "spraycan" to_actor $PLAYER_ACTOR with_offset -0.301 -0.2 0.17 rotation -5.5 -3.5 0.0 flag 1
0883: attach_particle 0@ to_actor $PLAYER_ACTOR on_bone 26
064C: make_particle 0@ visible

:SPRAYWP_13
0001: wait 0 ms
if
0256: player $PLAYER_CHAR defined
004D: jump_if_false @SPRAYWP_15
if or
00E1: key_pressed 0 17
00E1: key_pressed 0 6
0AB0: key_pressed 2// -- RMB
004D: jump_if_false @SPRAYWP_15
if
8965: not actor $PLAYER_ACTOR swimming
004D: jump_if_false @SPRAYWP_15
if or
02D8: actor $PLAYER_ACTOR current_weapon == 22
02D8: actor $PLAYER_ACTOR current_weapon == 23
02D8: actor $PLAYER_ACTOR current_weapon == 24
02D8: actor $PLAYER_ACTOR current_weapon == 28
02D8: actor $PLAYER_ACTOR current_weapon == 29
02D8: actor $PLAYER_ACTOR current_weapon == 32
004D: jump_if_false @SPRAYWP_15
0002: jump @SPRAYWP_13

:SPRAYWP_15
0976: destroy_particle 0@
0001: wait 1000 ms
0002: jump @SPRAYWP_01

为主的祥助 发表于 2012-4-7 10:58:43

本帖最后由 kwanz 于 2012-4-12 15:33 编辑

跳转列表

定义一个变量
1@ = 3

下面的代码用变量的值控制代码跳转的位置
0871: init_jump_table 1@ total_jumps 7 0 @JPTABL_T00 jumps 0 @JPTABL_T01 1 @JPTABL_T11 2 @JPTABL_T22 3 @JPTABL_T33 4 @JPTABL_T44 5 @JPTABL_T55 6 @JPTABL_T66
代码的格式是
<opcode> <指令描述符> <跳转变量> <指令描述符> <跳转分支数> <指令描述符> <缺省跳转指令> <7 x 跳转指令>
现在我们不看那堆opcode和英文,分析一下用法
参数1 - 指示变量
参数2 - 总跳转数
参数3+4 - 缺省跳转指令
参数5-14 - 分支跳转指令
支持的跳转数目:
Opcode 0871支持最多7个跳转指令
Opcode 0872支持最多9个跳转指令

变量值不在列表内时的缺省跳转(参数3+4)不计入跳转数之内

通过在0871跳转后追加0872语句,可以增多跳转分支的数目,最多支持75个。

0871: init_jump_table 1@ total_jumps 23 0 @JPTABL_T00 jumps 0 @JPTABL_T01 1 @JPTABL_T11 2 @JPTABL_T22 3 @JPTABL_T33 4 @JPTABL_T44 5 @JPTABL_T55 6 @JPTABL_T66
0872: jump_table_jumps 7 @JPTABL_T77 8 @JPTABL_T88 9 @JPTABL_T99 10 @JPTABL_T101 11 @JPTABL_T111 12 @JPTABL_T122 13 @JPTABL_T133 14 @JPTABL_T144 15 @JPTABL_T155
0872: jump_table_jumps 16 @JPTABL_T166 17 @JPTABL_T177 18 @JPTABL_T188 19 @JPTABL_T199 20 @JPTABL_T201 21 @JPTABL_T211 22 @JPTABL_T222 -1 @JPTABL_T00 -1 @JPTABL_T00
7重跳转的写法
0 @JPTABL_T01 1 @JPTABL_T11 2 @JPTABL_T22 3 @JPTABL_T33 4 @JPTABL_T44 5 @JPTABL_T55 6 @JPTABL_T66

一条跳转指令带有两个参数
0 @JPTABL_T01
第一个参数指定触发跳转的特定数值
第二个参数为条件满足时的跳转地址

以下是实例代码
按SHIFT改变天气
变量1@是跳转指示器
1@在跳转列表执行完毕后自加1
若1@大于6,则执行缺省跳转
<即1@的值不在跳转列表内>,
也就是跳转到@JPTABL_T00
{$CLEO .cs}
:JUMPTABLE
03A4: name_thread 'JPTABL'
1@ = 0

:JPTABL_1
0001: wait 0 ms
if
0256: player $PLAYER_CHAR defined
jf @JPTABL_1
03F0: enable_text_draw 1
045A: text_draw_1number 400.0 50.0 'NUMBER' 1@ // 显示数值
if1 q$ R& Q$ h% G! d7 G
0AB0: key_pressed 16 // -- shift
jf @JPTABL_1

:JPTABL_Table
0871: init_jump_table 1@ total_jumps 7 0 @JPTABL_T00 jumps 0 @JPTABL_T01 1 @JPTABL_T11 2 @JPTABL_T22 3 @JPTABL_T33 4 @JPTABL_T44 5 @JPTABL_T55 6 @JPTABL_T66

:JPTABL_T00// 缺省
00BA: text_styled 'fem_off' 1000 ms 4
wait 1000
0002: jump @JPTABL_1

:JPTABL_T01
01B6: set_weather 0// = Extra Sunny LA
0002: jump @JPTABL_EXIT

:JPTABL_T11
01B6: set_weather 1// = Sunny LA
0002: jump @JPTABL_EXIT

:JPTABL_T22
01B6: set_weather 2// = Sunny LA
0002: jump @JPTABL_EXIT

:JPTABL_T33
01B6: set_weather 3// = Sunny Smog LA
0002: jump @JPTABL_EXIT

:JPTABL_T44
01B6: set_weather 4// = Cloudy LA
0002: jump @JPTABL_EXIT

:JPTABL_T55
01B6: set_weather 5// = Sunny SF
0002: jump @JPTABL_EXIT

:JPTABL_T66
01B6: set_weather 6// = Extra Sunny SF
0002: jump @JPTABL_EXIT

:JPTABL_EXIT
1@ += 1
0001: wait 1000 ms
0002: jump @JPTABL_1

下面的代码是以上的加强版
用0872增加了16个跳转
{$CLEO .cs}
:JUMPTABLE
03A4: name_thread 'JPTABL'
1@ = 0

:JPTABL_1
0001: wait 0 ms
if
0256: player $PLAYER_CHAR defined
jf @JPTABL_1
03F0: enable_text_draw 1
045A: text_draw_1number 400.0 50.0 'NUMBER' 1@ // 显示数值
if
0AB0: key_pressed 16 // -- shift
jf @JPTABL_1

:JPTABL_Table
0871: init_jump_table 1@ total_jumps 23 0 @JPTABL_T00 jumps 0 @JPTABL_T01 1 @JPTABL_T11 2 @JPTABL_T22 3 @JPTABL_T33 4 @JPTABL_T44 5 @JPTABL_T55 6 @JPTABL_T66
0872: jump_table_jumps 7 @JPTABL_T77 8 @JPTABL_T88 9 @JPTABL_T99 10 @JPTABL_T101 11 @JPTABL_T111 12 @JPTABL_T122 13 @JPTABL_T133 14 @JPTABL_T144 15 @JPTABL_T155
0872: jump_table_jumps 16 @JPTABL_T166 17 @JPTABL_T177 18 @JPTABL_T188 19 @JPTABL_T199 20 @JPTABL_T201 21 @JPTABL_T211 22 @JPTABL_T222 -1 @JPTABL_T00 -1 @JPTABL_T00

:JPTABL_T00// 缺省

00BA: text_styled 'fem_off' 1000 ms 4
wait 1000
0002: jump @JPTABL_1

:JPTABL_T01
01B6: set_weather 0// = Extra Sunny LA
0002: jump @JPTABL_EXIT

:JPTABL_T11
01B6: set_weather 1// = Sunny LA
0002: jump @JPTABL_EXIT

:JPTABL_T22
01B6: set_weather 2// = Sunny LA
0002: jump @JPTABL_EXIT

:JPTABL_T33
01B6: set_weather 3// = Sunny Smog LA
0002: jump @JPTABL_EXIT

:JPTABL_T44
01B6: set_weather 4// = Cloudy LA
0002: jump @JPTABL_EXIT

:JPTABL_T55
01B6: set_weather 5// = Sunny SF
0002: jump @JPTABL_EXIT

:JPTABL_T66
01B6: set_weather 6// = Extra Sunny SF
0002: jump @JPTABL_EXIT

:JPTABL_T77
01B6: set_weather 7// = Cloudy SF
0002: jump @JPTABL_EXIT

:JPTABL_T88
01B6: set_weather 8// = Rainy SF
0002: jump @JPTABL_EXIT

:JPTABL_T99
01B6: set_weather 9// = Foggy SF
0002: jump @JPTABL_EXIT

:JPTABL_T101
01B6: set_weather 10// = Sunny LV
0002: jump @JPTABL_EXIT

:JPTABL_T111
01B6: set_weather 11// Extra Sunny LV
0002: jump @JPTABL_EXIT

:JPTABL_T122
01B6: set_weather 12// Cloudy LV
0002: jump @JPTABL_EXIT

:JPTABL_T133
01B6: set_weather 13// Extra Sunny Country
0002: jump @JPTABL_EXIT

:JPTABL_T144
01B6: set_weather 14// Sunny Country
0002: jump @JPTABL_EXIT

:JPTABL_T155
01B6: set_weather 15// Cloudy Country
0002: jump @JPTABL_EXIT

:JPTABL_T166
01B6: set_weather 16// Rainy Country
0002: jump @JPTABL_EXIT

:JPTABL_T177
01B6: set_weather 17// Extra Sunny Desert
0002: jump @JPTABL_EXIT

:JPTABL_T188
01B6: set_weather 18// Sunny Desert
0002: jump @JPTABL_EXIT

:JPTABL_T199
01B6: set_weather 19// Sandstorm Desert
0002: jump @JPTABL_EXIT

:JPTABL_T201
01B6: set_weather 20// Underwater
0002: jump @JPTABL_EXIT

:JPTABL_T211
01B6: set_weather 21// Extracolours 1
0002: jump @JPTABL_EXIT

:JPTABL_T222
01B6: set_weather 22// Extracolours 2
0002: jump @JPTABL_EXIT

:JPTABL_EXIT
1@ += 1
0001: wait 1000 ms
0002: jump @JPTABL_1

0494: get_joystick_data 0 1@ 2@ 3@ 4@
这个opcode读取玩家通过键盘,手柄做出的移动动作
具体键位由暂停菜单中>options>controller settings设定的<left/right> <forward/backward>有关

参数1: 玩家编号, player 1 = 0(主手柄), player 2 = 1(副手柄)
参数2: 左右移动的值
参数3: 前后移动的值
参数4,5: 未知

参数2,3返回的是正数或负数,你需要判定正负来判断是左/前移还是右/后移

下面是一个例子
{$CLEO .cs}
:Joystick_data
03A4: name_thread 'JOYDATA'

:JOYDATA_1
wait 0
0494: get_joystick_data 0 1@ 2@ 3@ 4@
if
1@ > 0
004D: jump_if_false @JOYDATA_04
03F0: enable_text_draw 1
045A: text_draw_1number 250.0 250.0 'NUMBER' 1@ // 显示值
0002: jump @JOYDATA_07

:JOYDATA_04
if
0 > 1@
004D: jump_if_false @JOYDATA_07
03F0: enable_text_draw 1
045A: text_draw_1number 350.0 250.0 'NUMBER' 1@ // 显示值
0002: jump @JOYDATA_07

:JOYDATA_07
if
2@ > 0
004D: jump_if_false @JOYDATA_09
03F0: enable_text_draw 1
045A: text_draw_1number 300.0 200.0 'NUMBER' 2@ // 显示值
0002: jump @JOYDATA_10

:JOYDATA_09
if
0 > 2@
004D: jump_if_false @JOYDATA_10
03F0: enable_text_draw 1
045A: text_draw_1number 300.0 300.0 'NUMBER' 2@ // 显示值
0002: jump @JOYDATA_10

:JOYDATA_10
0002: jump @JOYDATA_1

0A4A: store_joystick_X_offset_to 1@ Y_offset_to 2@
opcode 0A4A返回鼠标移动,以下代码试试便知
{$CLEO .cs}
:Mousecontrole
03A4: name_thread 'MOUSXY'

:MControl_01
wait 0
0A4A: store_joystick_X_offset_to 1@ Y_offset_to 2@
0092: 4@ = float_to_integer 1@
0092: 5@ = float_to_integer 2@
03F0: enable_text_draw 1
045A: text_draw_1number 200.0 50.0 'NUMBER' 4@ // value
045A: text_draw_1number 350.0 50.0 'NUMBER' 5@ // value
0002: jump @MControl_01

为主的祥助 发表于 2012-4-7 10:59:25

本帖最后由 kwanz 于 2012-4-13 13:15 编辑

瞬移,红圈和地点检测

先看一个简单的例子
在Grove St创建一个传送到CJ家屋顶上的红圈
{$CLEO .cs}
:Teleport_1
03A4: name_thread 'TELE'

:Teleport_2
wait 0
if
0256: player $PLAYER_CHAR defined
jf @Teleport_2
if
00FF: actor $PLAYER_ACTOR sphere 1 in_sphere 2493.5 -1682.5 13.35 radius 1.0 1.0 1.0 on_foot
jf @Teleport_2
00A1: put_actor $PLAYER_ACTOR at 2524.5 -1677.5 19.95
jump @Teleport_2
创建红圈需要调用opcode 00FF且把第二参数设为sphere 1 (sphere 0红圈不可见)
另外,必须把等待时间调为0ms,否则红圈不会显示。

例子:
:Teleport_2
wait 10
此时红圈不可见

另外很重要的一点,游戏能创建的红圈数是有限的
参考SB帮助: SCM Documentation: GTA Limits

还有一些Opcode可以显示红圈
下面是仅创建一个红圈的例子
03BC: 1@ = create_sphere_at 2493.5 -1682.5 13.35 radius 1.0
//注意最后要移除创建的红圈
03BD: destroy_sphere 1@

带小地图标记点的红圈
02A7: 0@ = create_icon_marker_and_sphere 35 at 2493.5 -1682.5 13.35
//或者可用下面这句
0570: 1@ = create_asset_radar_marker_with_icon 35 at -2007.8 189.1 27.5
//注意最后要移除创建的红圈
0164: disable_marker 0@
0164: disable_marker 1@地点检测00FE: actor $PLAYER_ACTOR sphere 1 in_sphere 2493.5 -1682.5 13.35 radius 15.0 15.0 15.0
00FF: actor $PLAYER_ACTOR sphere 1 in_sphere 2493.5 -1682.5 13.35 radius 1.0 1.0 2.0 on_foot
0100: actor $PLAYER_ACTOR in_sphere 2493.5 -1682.5 13.35 radius 4.0 4.0 4.0 sphere 1 in_car
0101: actor $PLAYER_ACTOR in_sphere 2493.5 -1682.5 13.35 radius 5.0 5.0 3.0 sphere 1 stopped
0102: actor $PLAYER_ACTOR in_sphere 2493.5 -1682.5 13.35 radius 1.2 1.2 3.0 sphere 1 stopped_on_foot
0103: actor $PLAYER_ACTOR in_sphere 2493.5 -1682.5 13.35 radius 4.0 4.0 6.0 sphere 1 stopped_in_car
0104: actor $PLAYER_ACTOR near_actor 1@ radius 15.0 15.0 15.0 sphere 1
0105: actor $PLAYER_ACTOR near_actor 1@ radius 5.0 5.0 2.0 sphere 1 on_foot

驾车地点检测
01AD: car 1@ sphere 1 near_point 2493.5 -1682.5 radius 6.0 6.0
01AE: car 1@ sphere 1 near_point 2493.5 -1682.5 radius 3.0 3.0 stopped
01AF: car 1@ sphere 1 in_sphere 2493.5 -1682.5 radius 0.2 0.2 1.0
01B0: car 1@ sphere 1 in_sphere 2493.5 -1682.5 13.35 radius 4.0 4.0 4.0 stopped

带红圈显示的地点检测语句是非常好用的,注意要把循环时间设置为0ms。

现在我们可以通过增加地点检测语句的方法,设定多个瞬移入口。
老家四个瞬移点:
{$CLEO .cs}
:Teleport_1
03A4: name_thread 'TELE'

:Teleport_2
wait 0
if
0256: player $PLAYER_CHAR defined
jf @Teleport_2
if
00FF: actor $PLAYER_ACTOR sphere 1 in_sphere 2493.5 -1682.5 13.35 radius 1.0 1.0 1.0 on_foot
jf @Teleport_3
00A1: put_actor $PLAYER_ACTOR at 2524.5 -1677.5 19.95
jump @Teleport_2

:Teleport_3
if
00FF: actor $PLAYER_ACTOR sphere 1 in_sphere 2530.5 -1678.5 19.95 radius 1.0 1.0 1.0 on_foot
jf @Teleport_4
00A1: put_actor $PLAYER_ACTOR at 2512.5 -1670.5 13.5
jump @Teleport_2

:Teleport_4
if
00FF: actor $PLAYER_ACTOR sphere 1 in_sphere 2507.5 -1673.5 13.4 radius 1.0 1.0 1.0 on_foot
jf @Teleport_5
00A1: put_actor $PLAYER_ACTOR at 2490.5 -1717.5 18.6
jump @Teleport_2

:Teleport_5
if
00FF: actor $PLAYER_ACTOR sphere 1 in_sphere 2504.5 -1719.5 18.6 radius 1.0 1.0 1.0 on_foot
jf @Teleport_2
00A1: put_actor $PLAYER_ACTOR at 2497.5 -1681.5 13.4
jump @Teleport_2

Doge 发表于 2012-4-7 13:07:28

Ferdinand_os 发表于 2012-4-8 10:37:26

顶个吧!虽然看不懂- -,
页: [1] 2 3
查看完整版本: 【CLEO教学系列】CLEO脚本教程(未完工)