Hoofdpagina > Modding > Modding Tutorial List > Basis SCM-Scripten
Sanny Builder
Allereerst zal ik jullie wat basis leren over het programma wat we gebruiken: Sanny Builder. Er zijn een aantal handige dingen om te weten, waardoor het scripten een stuk leuker en eenvoudiger wordt. Maar we zullen beginnen bij het begin: het decompileren.
Decompileren
Ga naar Run > Decompile. Dit kan ook door op het tekentje in de balk te klikken, of op F5 te drukken. Dit kan je hieronder zien op screen 1. Ga vervolgens naar: Program Files > Rockstar Games > GTA San Andreas > data > script (screen 2). Dan zie je de code, die je kunt editten (screen 3).
Kleurtjes in Sanny Builder
Nu kun je gaan editten. Handig aan Sanny builder is dat de tekst kleurtjes heeft:
- Zwart: dit is bij bepaalde vaak gebruikte (waar je vaak ook geen code voor hoeft te zetten), zoals jump, wait, create_thread, fade, repeat, jf, etcetera.
- Groen: dit is de naam van een label, bijvoorbeeld ":label" of "@label" (achter een jump ofzo).
- Blauw: de variabelen hebben een blauwe kleur
- Rood: namen van bijvoorbeeld objecten, teksten en threads zijn rood.
- Geel en blauw: deze zijn achter elkaar te vinden in een file. De gele is het "object" wat bedoeld wordt, de blauwe is wat iets over het eerste zegt. Misschien moeilijk uit te leggen, maar als je even bekijkt snap je het wel. ;)
- Bruin: namen van models
- Blauw/grijs (lichter): dit staat achter //, wat als kladblaadje kan functioneren. Dit wordt niet gelezen door het spel, en dient alleen als kladblaadje voor de modder(s).
Handige functies in Sanny Builder
Er zijn een aantal functies in SannyBuilder die erg handig zijn om te gebruiken:
- Coords manager, te vinden in: Tools > Ide Tools > Coords Manager (sneltoets: CTRL+ALT+1). Hiermee vind je gelijk de X, Y en Z coordinaat én de hoek waarmee je op dat moment in SA staat. Dit kan je niet aanklikken als je SA niet aanstaat.
- Opcode search, te vinden in: Tools > Ide Tools > Coords Manager (sneltoets: CTRL+ALT+2). Hiermee kan je makkelijk zoeken naar opcodes.
- De F1 toets is erg handig. Als je iets typt, bijvoorbeeld de begincode van een opcode, dan krijg je gelijk het volledige te zien. Ook andere dingen kan je intypen Een soort zoekfunctie dus.
- Contents, te vinden onder "HELP", met als sneltoets F12. Hierbij vind je een hele grote documentatiebank, als je op SCM Documentation klikt. Heel handig als je bijvoorbeeld een bepaald icon-nummer zoekt, of één van de vele andere dingen.
- Je kunt vanuit Sanny gelijk SA opstarten, door op het icoontje "Run San Andreas" of F8 te drukken.
- Er is een code converter van San Andreas Mission Builder naar Sanny Builder, maar die werkt niet vlekkeloos. Als je het toch wilt doen, wat ik je niet aanraad, ga dan naar Tools > Code Converter > MB -> SB.
Als je klaar bent met editten, moet je het weer compileren. Dit doe je door op Run > Compile te klikken, of op het icoontje, of op F6. Je hebt ook nog een andere functie om te compileren, namelijk Compile + Copy, F7. Dit betekent dat het altijd in de map GTA San Andreas > Data > Script wordt opgeslagen, dus niet op de plaats waar jij het bestand op dat moment hebt staan.
Natuurlijk heeft Sanny Builder nog meer mogelijkheden, maar dit zijn de belangrijkste.
Het scripten
Threads
Je kunt het script zien alsof er een mannetje doorheen loopt. Soms komt dat mannetje bij een punt aan, waar hij zich verdubbeld: "create_thread". Ze leven dan beide door, maar het originele mannetje gaat door vanaf "create_thread", terwijl het gekloonde mannetje doorgaat op de plaats waar je een nieuwe thread wilt laten starten. Dus bijvoorbeeld: create_thread @boe, dan gaat het mannetje verder bij :boe. Als een mannetje bij het commando "end_thread" komt, gaat hij dood. Dan loopt die dus niet verder door de code. Er kunnen dus heel veel mannetje tegelijk lopen (er komt immers bij iedere "create_thread" een nieuw mannetje), die ieder hun eigen werkzaamheden op hetzelfde moment aan het doen zijn. De mannetjes werken onafhankelijk van elkaar.
De missies zijn een apart soort thread, en worden dan ook niet aangegeven met "create_thread", maar met "start_mission". Het zorgt er bijvoorbeeld voor dat je maar één missie tegelijk kunt beginnen. Het aparte is dat er door heel het script wordt gecontroleerd of je "wasted" of "busted" bent, en niet alleen wanneer dat commando er staat. Als de player wasted of busted is doet het mannetje van de missie thread alsof hij een "return" tegenkomt. Daarom moeten missies ook altijd beginnen met een bepaalde structuur..
Labels/jump/gosub
Labels worden aangegeven met ":" ervoor. Het zijn namen die worden toegekend aan bepaalde plekken/locaties/punten in het script. Dit is handig om ernaar toe te kunnen springen. Dit kan met "gosub" en "jump".
:MAIN_4059 01B7: release_weather jump @MAIN_4075
Hierboven zie je een label, namelijk "MAIN_4059". Vervolgens zie je een commando, met een code ervoor. Die code heet een opcode. Daaronder zie je een ander commando, namelijk jump. Met die @... geef je aan dat je naar een label springt. Je springt dus naar het label: :MAIN_4075.
Gosub is een ander verhaal. Daarmee springt hij naar een ander label, en gaat hij weer terug nadat het script "return" gelezen heeft. Voorbeeld:
:MS_GAME_BEEFYBARON $ONMISSION = 1 // integer values 00BA: text_styled 'BEEFY' 1000 ms 2 // Beefy Baron gosub @SUB_FADE_500MS start_mission 10 // Beefy Baron jump @END_CASE_VIDEO_GAME
:SUB_FADE_500MS 0169: set_fade_color 0 0 0 fade 0 500 :LITCAS_282 if fading else_jump @LITCAS_306 wait 0 jump @LITCAS_282 :LITCAS_306 Return
Hierboven springt hij dus eerst met "gosub" naar :SUB_FADE_500MS. Daar gaat het script erdoorheen en gaat pas terug na het commando "return" (LITCAS_306). Na "return" gaat hij dus weer terug naar de gosub, in MS_GAME_BEEFYBARON dus.
De reden waarom "gosub" gebruikt wordt in plaats van 2x jump, is omdat het dan altijd standaard terug gaat naar de plaats waar hij vandaan komt. Meerdere mannetjes kunnen dan afzonderlijk van elkaar springen naar het label waar gosub naar verwijst, en terugkomen naar het stukje waar ze vandaan komen. Bij "jump" gaat hij echter altijd naar hetzelfde label terug. Gosub komt van subroutine.
Conditionele jump
Er is ook nog zoiets als de "conditionele jump". Dan checkt het mannetje het script, en kijkt of er iets gebeurd is. Is dat niet gebeurd, dan jump je ergens anders naar toe. Is dat wel gebeurd, dan gaat het script gewoon door. Hiervoor kan je drie dingen gebruiken: "else_jump @boe" "jf @boe" "004D: jump_if_false @boe"
In Sanny Builder wordt meestal één van de twee bovenste gebruikt, omdat bij de derde ook de opcode (004D) gebruikt moet worden.
:SWEET4_103 if Model.Available(#GREENWOO) else_jump @SWEET4_152
In dit voorbeeld wordt gekeken of een model beschikbaar is (het model van de Greenwood, in dit geval). Als dat niet het geval is, dan springt hij naar het label ":SWEET4_152". Is dit wel het geval, dan gaat hij gewoon door.
Je kunt hier ook een lus van maken, dan wacht het mannetje net zo lang tot aan de voorwaarde gedaan wordt. Let wel op, dat je dan een wait moet plaatsen! In alle lussen, moet een wait. Als je dat vergeet, slaat het spel vast. Vaak kan je hierdoor niets meer, ook niet terug naar je bureaublad, waardoor je genoodzaakt bent om je pc opnieuw op te starten. Een voorbeeld van zo’n lus is:
:SWEET4_103 Wait 0 ms if Model.Available(#GREENWOO) else_jump @SWEET4_103[/code]
Zoals je ziet, blijft hij, zolang het model niet beschikbaar is, terugspringen naar het begin van dit label. Is dat wel het geval, dan gaat hij door.
Conditionele gosub
Naast een conditionele jump, is er ook een conditionele gosub (bestaat alleen bij CLEO3!!!):
0AA0: gosub_if_false @CREATE_NEW_ACTOR
Dit werkt precies hetzelfde als een conditionele jump (alleen dan met een gosub). Dit wordt echter niet zo vaak gebruikt (met als voornaamste reden dat hij met CLEO3 werkt)…
If-then-end structuur
Er zijn nog andere structuren, buiten de jump_if_false, waarmee je kunt checken of iets gebeurd. Een voorbeeld hiervan is de if-then-end structuur (deze heb ik zelf geschreven, dus is niet terug te vinden in de main van sa):
if $choice == 0 then $money = 10 End
Wanneer de variabele $choice gelijk is aan 0, dan wordt de waarde van de variabele "$money" gelijk aan 10. Is $choice niet gelijk aan 0? Dan gebeurt er gewoon niets. De end is nodig om aan te geven vanaf waar de voorwaarde niet meer geld, dus wat het mannetje altijd moet lezen, ook als $choise niet gelijk is aan 0. Je kunt dus bij $money nog veel meer dingen zetten die moeten gebeuren als $choice gelijk is aan 0.
Repeat-wait-until structuur
repeat wait 0 ms until 03D0: wav 3 loaded
Dit is een voorbeeld van een repeat-wait-until structuur. Aangezien dit weer een lus is, moet er weer een wait bijstaan. Hier staat: blijf alles doen wat tussen repeat en until staat, tot de voorwaarde bereikt is. Tussen repeat en until kunnen ook andere dingen staan, bijvoorbeeld dat je in een auto moet blijven zitten. In plaats van dit kan je het ook in de vorm van een conditionele jump schrijven:
:label wait 0 ms if 03D0: wav 3 loaded else_jump @label
Getallen
Er zijn 2 mogelijke getallen: Integer Values: hele, natuurlijke getallen (1; 2; 3) Floating-point values: kommagetallen (1,5345; 3,4)
Floating-point values worden meestal gebruikt bij coördinaten, of andere coördinaten gerelateerde zaken, als bijvoorbeeld snelheid.
Voor de overige dingen worden vaak Integer Values gebruikt. Het voordeel aan Integer Values gebruiken, is dat de computer er makkelijk mee kan rekenen. Deze worden bijvoorbeeld gebruikt om wachttijden in te stellen. Maar ook als identificatie getallen voor bepaalde objecten, en om sprongen binnen het script te berekenen.
De IV en FPV mogen niet door elkaar gebruikt worden, het script werkt dan niet. Bij coördinaten is het dan ook handig om gewoon altijd floating-point values te gebruiken. Om een voorbeeld te geven, als je bij een coördinaat 100.0 in wilt vullen, en je tikt 100, dan slaat hij de waarde 100 als integer op. Later als het script in het spel draait, wordt dat door een commando als floating-point value gezien, en komt er iets heel anders uit (geen 100.0, wat de bedoeling was).
0004: $3412 = 5000 ;; integer values 0084: $3413 = $3412 ;; integer values and handles
Het verschil is dat de eerste een waarde toekent aan een globale variable, in dit geval de waarde 5000, aan de globale variabele $3412. Dus hier staat in feiten: $3413 = $3412 = 5000, al mag je dit zo nooit in main.scm schrijven, daarin moet je hem opsplitsen.
Variabelen
Er zijn twee soorten variabelen: globale en lokale variabelen. Globale worden aangegeven met een $ ervoor (bijvoorbeeld $boe), lokale met een @ erachter (2@). Let op: een lokale variabele bestaat uit alleen maar cijfers, een globale mag nooit uit alleen maar cijfers staan. Daar wordt de code heel instabiel van, en soms werkt het gewoon niet (ook al doet Rockstar het zelf ook wel eens). Het verschil tussen globale en lokale variabelen is eigenljk vrij simpel: een globale variabele gebruik je in heel het script. Dus als je $boe gelijk stelt aan 5, dan is $boe overal 5 (tenzij je het weer veranderd). Lokale variabele daarentegen, gelden allee binnen één thread. Als je 1@ in een bepaalde thread aanmaakt, en vervolgens hetzelfde getal in een andere thread wilt gebruiken, dan moet je aan 1@ opnieuw een waarde toekennen. De waarde uit de andere thread geldt niet meer.
Rekenen met variabelen
In het SCM scripten moet je ook wel rekenen met variabelen. Hier zijn een aantal opcodes voor. Let op, hier kán je verschillen hebben in integer-values en floating-point-values, of verschil in globale en lokale variabelen. Je kunt optellen, aftrekken, vermenigvuldigen en delen. Daarnaast kan je iets gelijk stellen aan iets anders. Hieronder staan een aantal voorbeelden: [code]0008: $variabele += 1[/code] Hierbij wordt de globale variabele vermeerderd met 1.
000A: 3@ += 3000
Deze opcode doet in feiten hetzelfde als hierboven, maar dan een lokale variabele. Zoals je ziet is er toch een verschil in opcode, de een is 0008, de andere is 000A.
000B: 6@ += 0.1
Misschien zie je zelf al wel wat het verschil is met hierboven. Dit is een floating-point-value, die hierboven is een integer value.
0009: $variabele += 1.741
Vrijwel dezelfde als de bovenste, maar ook dit keer is het een floating-point-value en geen integer.
Dit zijn alleen de opcodes voor het vermeerderen van een variabele. Zo heb je ze ook met delen, vermenigvuldigen en aftrekken. Ook kan je variabelen bij andere variabelen tellen, bijvoorbeeld:
0058: $1924 += $1929 // (int)
Stel dat $1924 de waarde 5 heeft, en $1929 de waarde 3. Dan heeft $1924 vanaf deze opcode de waarde 8 (5 + 3).
0038: $672 == 1
Dit is een code waarmee je checkt of de variabele gelijk is aan 1. Dit is dus niet de variabele gelijkstellen.
0004: $var = 0
Dit is wél de variabele gelijkstellen aan 0.