In deze tutorial ga ik uitleggen hoe je een emergency light system/emergency light mod kan maken voor GTA:SA. Dit houdt in dat we een knipperend effect geven aan de lichten van voertuigen.
Het belangrijkste deeltje van de code is natuurlijk de lichten van de auto aan of uit laten gaan. Dit is echter niet zo vanzelfsprekend, er is namelijk geen enkele opcode die ons toelaat om dit te doen. Maar gelukkig is het wel mogelijk door een beetje in het geheugen van het spel te werken.
■ De tweede lijn zorgt ervoor dat 9@ nu wijst naar het adres dat 1440 (=0x5A0 hex) bytes verder geplaatst is. Deze wijst naar de damage handler van de auto. (veronderstelling)
■ Op de derde lijn wordt de method die op geheugenadres 0x6C2100 zit aangeroepen vanuit de damage handler die 9@ aanwijst. Deze mehtod is SetLightStatus en zal dus de staat van een licht aansturen.
1) Memory address van method die we willen gebruiken
2) Memory address van de structuur van de damage handler van de auto
3) Aantal parameters er meegegeven worden
4) Aantal parameters dat verwijderd moeten worden uit de stack nadat de method uitgevoerd is.
5) De parameters die doorgegeven moeten worden naar de method die aangeroepen wordt, in dit geval een parameter die aangeeft of het licht aan of uit moet zijn, en het nummer van het licht.
Standaard kun je de achterlichten niet apart aan- of uitzetten. Maar dit kan opgelost worden door:
0A8C: write_memory 0x6E1D4F size 1 value 2 vp 0
Dit heb ik gevonden in de source van mtasa. Er staat bij dat dit een bug is in het spel, maar ik denk dat het ook zou kunnen dat het gewoon iets onafgewerkts is (in de video kun je namenlijk zien dat de achterlichten van hotring racer A nog steeds niet apart werken).
Edit:
Op 27-6-2015 om 14:54, Big Boss zei:
Dat komt omdat het model beide lichten definiëert als zijnde "links achter". Als je deze toewijzing in het model verandert dan zullen ze wel apart werken. Zie het model van Hotring A en ter vergelijking het model van de gewone Hotring.
Nu hebben we volgende lichtnummers: 0 voorzijde links | 1 voorzijde rechts | 2 achterzijde links | 3 achterzijde rechts
Om hiermee gemakkelijk te kunnen werken had ik het idee om verschillende stukjes code te maken waar we naartoe kunnen gosub'en om de voorlichten of achterlichten te kunnen sturen.
:FL // front left
0AA6: call_method 0x6C2100 struct 9@ num_params 2 pop 0 param_destroyed 0 param_light_nr 0
0AA6: call_method 0x6C2100 struct 9@ num_params 2 pop 0 param_destroyed 1 param_light_nr 1
return
:FR // front right
0AA6: call_method 0x6C2100 struct 9@ num_params 2 pop 0 param_destroyed 1 param_light_nr 0
0AA6: call_method 0x6C2100 struct 9@ num_params 2 pop 0 param_destroyed 0 param_light_nr 1
return
:FB // front both
0AA6: call_method 0x6C2100 struct 9@ num_params 2 pop 0 param_destroyed 0 param_light_nr 0
0AA6: call_method 0x6C2100 struct 9@ num_params 2 pop 0 param_destroyed 0 param_light_nr 1
return
:FN // front none
0AA6: call_method 0x6C2100 struct 9@ num_params 2 pop 0 param_destroyed 1 param_light_nr 0
0AA6: call_method 0x6C2100 struct 9@ num_params 2 pop 0 param_destroyed 1 param_light_nr 1
return
:BL // back left
0AA6: call_method 0x6C2100 struct 9@ num_params 2 pop 0 param_destroyed 0 param_light_nr 2
0AA6: call_method 0x6C2100 struct 9@ num_params 2 pop 0 param_destroyed 1 param_light_nr 3
return
:BR // back right
0AA6: call_method 0x6C2100 struct 9@ num_params 2 pop 0 param_destroyed 1 param_light_nr 2
0AA6: call_method 0x6C2100 struct 9@ num_params 2 pop 0 param_destroyed 0 param_light_nr 3
return
:BB // back both
0AA6: call_method 0x6C2100 struct 9@ num_params 2 pop 0 param_destroyed 0 param_light_nr 2
0AA6: call_method 0x6C2100 struct 9@ num_params 2 pop 0 param_destroyed 0 param_light_nr 3
return
:BN // back none
0AA6: call_method 0x6C2100 struct 9@ num_params 2 pop 0 param_destroyed 1 param_light_nr 2
0AA6: call_method 0x6C2100 struct 9@ num_params 2 pop 0 param_destroyed 1 param_light_nr 3
return
Dus om bijvoorbeeld het linkervoorlicht te laten werken en het rechtervoorlicht te laten doven kunnen we dit met 1 lijntje doen:
0050: gosub @FL
Nu kun je even uitblazen want hier is het moeilijkste gedeelte al achter de rug
Variabelen toekennen
Hier ga ik plaatsen welk variabelen we voor wat gaan gebruiken, dit kan handig zijn om op terug te vallen als je even niet meer weet wat je aan het doen bent of als je de code na een lange tijd terugziet.
// vars:
// 1@ ELS enabled?
// 4@ zit speler in auto?
// 5@ patroon index
// 8@ player car
// 9@ damage handler pointer voor player car
// 33@ pattern delay timer
Alle andere nummers die je eventueel tegenkomt, zijn tijdelijke variablen.
32@ en 33@ zijn speciale timer-variabelen, deze worden elke milliseconde verhoogd met 1. Dit kan handig zijn als je een missie hebt met tijdsbeperking of als je een vertraging nodig hebt zoals hier: anders zou het misschien zo snel gaan dat je het niet deftig kan zien. Soms is dit ook te verkiezen boven een wait, want bij een wait kun je namelijk niets anders doen, maar als je een timer variabele gebruikt kun je bijvoorbeeld ondertussen nog kijken of de speler op een bepaalde toets drukt voor een menu te tonen.
Incar subroutine
Dit is een subroutine die gaat checken of de speler in een auto zit. Als dit zo is, zetten we 4@ op 1 en 9@ naar de damage handler pointer. Dit kunnen we dan aanroepen door een simpele gosub te gebruiken.
4@ geeft aan of de speler in een auto zit
9@ wijst naar de damage handler van de auto (zie eerste puntje: belangrijkste code + uitleg)
:INCAR
0006: 4@ = 0 //incar
00D6: if and
00DF: actor $PLAYER_ACTOR driving
84C8: not actor $PLAYER_ACTOR driving_flying_vehicle
84A9: not actor $PLAYER_ACTOR driving_heli
84A7: not actor $PLAYER_ACTOR driving_boat
847A: not actor $PLAYER_ACTOR driving_bike
004D: jf @INCAR_1
0006: 4@ = 1 //incar
03C0: 8@ = actor $PLAYER_ACTOR car
0A97: 9@ = car 8@ pointer
000A: 9@ += 0x5A0
:INCAR_1
return
code map
Spoiler
Toggle subroutine
Deze subroutine zal de staat verwisselen. Als het effect niet actief is, dan deze aanzetten, tekst tonen, variables resetten en een geluidje afspelen. Anders uitzetten, tekst tonen en een geluidje afspelen.
Hier gaan we de patronen aansturen. Dit is het masterplan:
in 5@ zit de zgn 'pattern index', deze geeft aan in hoeverre het patroon zit. Dit zal van 0 tot 23 lopen (dus 24 verschillende staten). Afhankelijk van deze pattern index zullen we de staat van lichten veranderen. Zowel de voorlichten als achterlichten zullen een eigen patroon hebben.
De patronen die ik ga gebruiken staan in commentaar. L = links en R = rechts, - wil zeggen alles uit. Dan moeten we naar de juiste labels springen om de lichten veranderen enkel als het nodig is. Dus bv als er een - na een - komt hoeft er niets te gebeuren want de lichten zitten al in die staat.
Dit kan gemakkelijk geïmplementeerd worden door jump tables. Voor de mensen die al wat van programmeren kennen: dit lijkt goed op een switch statement.
// -------------- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
// front pattern: L - L - - - R - R - - - L - L - - - R - R - - -
:PATTERN_FRONT
0871: switch 5@ total_cases 16 default_case -1 @R case 0 @FL case 1 @FN case 2 @FL case 3 @FN case 6 @FR case 7 @FN case 8 @FR
0872: switch_continued case 9 @FN case 12 @FL case 13 @FN case 14 @FL case 15 @FN case 18 @FR case 19 @FN case 20 @FR case 21 @FN
Deze code wil zeggen dat we de waarde van 5@ zullen bekijken & er zijn 16 verschillende waardes waarvoor we kunnen jumpen naar een label. Als de waarde niet overeenkomt met een van die ingestelde waardes, gebruik de default jump (-1) en die gaat naar :R (dit is gewoon een label met een return statement erna). De rest van de waardes staan na elkaar. Bv als 5@ 0 is, jump naar :FL, bij 1 jump naar :FN etc etc.
In 0871 kunnen we 7 waardes zetten, hiermee hebben we echter niet genoeg maar gelukkig is er nog 0872 waarmee we de jump table kunnen uitbreiden. Hiermee hebben we net genoeg voor dit patroon, maar je kunt de jump table meerdere keren uitbreiden.
De labels zijn van de stukjes die ik in het begin heb gezet (belangrijkste code + uitleg).
// ------------- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
// back pattern: L L L R R R L L L R R R L L L R R R L L L R R R
:PATTERN_BACK
0871: switch 5@ total_cases 8 default_case -1 @R case 0 @BL case 3 @BR case 6 @BL case 9 @BR case 12 @BL case 15 @BR case 18 @BL
0872: switch_continued case 21 @BR case -1 @R case -1 @R case -1 @R case -1 @R case -1 @R case -1 @R case -1 @R case -1 @R
Merk op dat er hier op het einde allemaal -1 @R staat. Dit is omdat die opcode zoveel parameters verwacht, en we kunnen die niet leeglaten dus zetten we er meestal hetzelfde als bij de default case.
Deze zullen we ook oproepen met gosub.
Hoofdcode
Nu hebben we alle subroutines en kunnen we beginnen aan de main code.
:ELS_START duidt het begin aan van de loop. Hier staat er ook een wait 0 omdat dit een oneindige loop is en het spel kan anders niets anders doen.
pseudocode
variablen initialiseren
:ELS_START
wait 0
voor subroutine bij @INCAR uit
als 4@ niet 1 is (dus als speler niet in auto zit), jump terug naar @ELS_START
anders
als de speler niet f12 indrukt, ga naar @ELS_START_PATTERN en voer het patroon uit
anders
voor subroutine bij @TOGGLE uit om de staat de veranderen
wacht een beetje zodat de speler de toets kan loslaten
jump terug naar @ELS_START
Bij :ELS_START_PATTERN gaan we het patroon aansturen. Hier zullen we een vertraging insteken zodat het patroon niet te snel zal gaan. Zoals eerder vermeld gaan we hiervoor timer 33@ gebruiken. 5@ geeft de index aan van het patroon.
pseudocode
als het niet aan staat of 33@ is minder dan 75, jump naar het begin (@ELS_START)
anders
forceer de lichten op aan (zodat de lichten ook overdag aan zijn).
voor subroutine bij @PATTERN_FRONT uit om de voorlichten aan te sturen
voor subroutine bij @PATTERN_BACK uit om de achterlichten aan te sturen
timer 33@ resetten op 0
pattern index 5@ verhogen, als dit meer is dan 23: terug op 0 zetten
jump naar het begin (@ELS_START)
{$CLEO .cs}
03A4: name_thread 'ELS'
// vars:
// 1@ ELS enabled?
// 4@ zit speler in auto?
// 5@ patroon index
// 8@ player car
// 9@ damage handler pointer voor player car
// 33@ pattern delay timer
0006: 1@ = 0
0006: 5@ = 0
// Fix vehicle back lights both using light state 3 (SA bug)
// https://github.com/multitheftauto/mtasa-blue/blob/c0a35ccd2b7704c92907fd48f66eeea869e533a4/MTA10/multiplayer_sa/CMultiplayerSA.cpp#L1247
0A8C: write_memory 0x6E1D4F size 1 value 2 vp 0 // default value: 3
// ----------------------------------------------------------------------------
// main start point
:ELS_START
0001: wait 0
0050: gosub @INCAR
00D6: if
0039: 4@ == 1 //incar
004D: jf @ELS_START
00D6: if
0AB0: key_pressed 0x7B // f12
004D: jf @ELS_START_PATTERN
0050: gosub @TOGGLE
0001: wait $DEFAULT_WAIT_TIME // prevent double key
0002: jump @ELS_START
:ELS_START_PATTERN
00D6: if and
0039: 1@ == 1 //enabled
0019: 33@ > 75 // pattern delay
004D: jf @ELS_START
067F: force_car 8@ lights_to 2 // 0 = NO_CAR_LIGHT_OVERRIDE | 1 = FORCE_CAR_LIGHTS_OFF | 2 = FORCE_CAR_LIGHTS_ON
0050: gosub @PATTERN_FRONT
0050: gosub @PATTERN_BACK
0006: 33@ = 0
000A: 5@ += 1 // pattern index
00D6: if
0019: 5@ > 23
004D: jf @ELS_START
0006: 5@ = 0
0002: jump @ELS_START
// ----------------------------------------------------------------------------
// pattern control
// -------------- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
// front pattern: L - L - - - R - R - - - L - L - - - R - R - - -
:PATTERN_FRONT
0871: switch 5@ total_cases 16 default_case -1 @R case 0 @FL case 1 @FN case 2 @FL case 3 @FN case 6 @FR case 7 @FN case 8 @FR
0872: switch_continued case 9 @FN case 12 @FL case 13 @FN case 14 @FL case 15 @FN case 18 @FR case 19 @FN case 20 @FR case 21 @FN
// ------------- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
// back pattern: L L L R R R L L L R R R L L L R R R L L L R R R
:PATTERN_BACK
0871: switch 5@ total_cases 8 default_case -1 @R case 0 @BL case 3 @BR case 6 @BL case 9 @BR case 12 @BL case 15 @BR case 18 @BL
0872: switch_continued case 21 @BR case -1 @R case -1 @R case -1 @R case -1 @R case -1 @R case -1 @R case -1 @R case -1 @R
:R
return
// ----------------------------------------------------------------------------
// light control
:FL // front left
0AA6: call_method 0x6C2100 struct 9@ num_params 2 pop 0 param_destroyed 0 param_light_nr 0
0AA6: call_method 0x6C2100 struct 9@ num_params 2 pop 0 param_destroyed 1 param_light_nr 1
return
:FR // front right
0AA6: call_method 0x6C2100 struct 9@ num_params 2 pop 0 param_destroyed 1 param_light_nr 0
0AA6: call_method 0x6C2100 struct 9@ num_params 2 pop 0 param_destroyed 0 param_light_nr 1
return
:FB // front both
0AA6: call_method 0x6C2100 struct 9@ num_params 2 pop 0 param_destroyed 0 param_light_nr 0
0AA6: call_method 0x6C2100 struct 9@ num_params 2 pop 0 param_destroyed 0 param_light_nr 1
return
:FN // front none
0AA6: call_method 0x6C2100 struct 9@ num_params 2 pop 0 param_destroyed 1 param_light_nr 0
0AA6: call_method 0x6C2100 struct 9@ num_params 2 pop 0 param_destroyed 1 param_light_nr 1
return
:BL // back left
0AA6: call_method 0x6C2100 struct 9@ num_params 2 pop 0 param_destroyed 0 param_light_nr 2
0AA6: call_method 0x6C2100 struct 9@ num_params 2 pop 0 param_destroyed 1 param_light_nr 3
return
:BR // back right
0AA6: call_method 0x6C2100 struct 9@ num_params 2 pop 0 param_destroyed 1 param_light_nr 2
0AA6: call_method 0x6C2100 struct 9@ num_params 2 pop 0 param_destroyed 0 param_light_nr 3
return
:BB // back both
0AA6: call_method 0x6C2100 struct 9@ num_params 2 pop 0 param_destroyed 0 param_light_nr 2
0AA6: call_method 0x6C2100 struct 9@ num_params 2 pop 0 param_destroyed 0 param_light_nr 3
return
:BN // back none
0AA6: call_method 0x6C2100 struct 9@ num_params 2 pop 0 param_destroyed 1 param_light_nr 2
0AA6: call_method 0x6C2100 struct 9@ num_params 2 pop 0 param_destroyed 1 param_light_nr 3
return
// ----------------------------------------------------------------------------
// incar subroutine
:INCAR
0006: 4@ = 0 //incar
00D6: if and
00DF: actor $PLAYER_ACTOR driving
84C8: not actor $PLAYER_ACTOR driving_flying_vehicle
84A9: not actor $PLAYER_ACTOR driving_heli
84A7: not actor $PLAYER_ACTOR driving_boat
847A: not actor $PLAYER_ACTOR driving_bike
004D: jf @INCAR_1
0006: 4@ = 1 //incar
03C0: 8@ = actor $PLAYER_ACTOR car
0A97: 9@ = car 8@ pointer
000A: 9@ += 0x5A0
:INCAR_1
return
// ----------------------------------------------------------------------------
// toggle subroutine
:TOGGLE
00D6: if
0039: 1@ == 1 //enabled
004D: jf @ENABLE
0AD0: show_formatted_text_lowpriority "ELS ~r~disabled" time 2000
0006: 1@ = 0
067F: force_car 8@ lights_to 1 // 1 = FORCE_CAR_LIGHTS_OFF
018C: play_sound 1053 at 0.0 0.0 0.0
return
:ENABLE
0AD0: show_formatted_text_lowpriority "ELS ~g~enabled" time 2000
0006: 1@ = 1
0006: 33@ = 0 // reset timer
018C: play_sound 1052 at 0.0 0.0 0.0
return
0A93: end_custom_thread
Volledige code map:
Spoiler
In SA-MP zullen de andere spelers het enkel kunnen zien als het nacht is, aangezien de lichten zogezegd niet aanstaan tijdens de dag. Ook zullen de achterlichten voor de andere spelers ofwel beide aan of uit zijn, tenzij ze ook deze mod hebben of een andere die de waarde aanpast die dit fixt.
Nu kun je het natuurlijk uitbreiden, misschien meerdere patronen, een mooi menu'tje?
Edits:
28/06/2015 quote van @Big Boss mbt hotring racer bijgezet
Simpele ELS mod
In deze tutorial ga ik uitleggen hoe je een emergency light system/emergency light mod kan maken voor GTA:SA. Dit houdt in dat we een knipperend effect geven aan de lichten van voertuigen.
Benodigdheden
CLEO3 of hoger
Sannybuilder
GTA:SA v1 of v1.01
We maken gebruik van geheugenadressen, waardoor dit hoogstwaarschijnlijk niet zal kloppen voor andere versies
SCM-kennis
Basiskennis is een vereiste (Basis SCM-scripten: tutorial door @Dutchy3010 & @PatrickW)
We zullen ook werken met het geheugen (Werken met geheugen (adressen) in CLEO: tutorial door @Crypteq)
Inhoud
Belangrijkste code + uitleg
Variabelen toekennen
Incar subroutine
Toggle subroutine
Pattern control subroutines
Hoofdcode
Patroon aansturen
Finito
Belangrijkste code + uitleg
Het belangrijkste deeltje van de code is natuurlijk de lichten van de auto aan of uit laten gaan. Dit is echter niet zo vanzelfsprekend, er is namelijk geen enkele opcode die ons toelaat om dit te doen. Maar gelukkig is het wel mogelijk door een beetje in het geheugen van het spel te werken.
De basiscode ziet er zo uit:
■ De eerste lijn zorgt ervoor dat in 9@ het geheugenadres komt waar de structuur van auto 8@ opgeslagen zit.
Op de lijst van geheugenadressen kan je zien wat je daar allemaal kunt vinden.
■ De tweede lijn zorgt ervoor dat 9@ nu wijst naar het adres dat 1440 (=0x5A0 hex) bytes verder geplaatst is. Deze wijst naar de damage handler van de auto. (veronderstelling)
■ Op de derde lijn wordt de method die op geheugenadres 0x6C2100 zit aangeroepen vanuit de damage handler die 9@ aanwijst. Deze mehtod is SetLightStatus en zal dus de staat van een licht aansturen.
Opcode 0AA6 heeft een aantal parameters:
1) Memory address van method die we willen gebruiken
2) Memory address van de structuur van de damage handler van de auto
3) Aantal parameters er meegegeven worden
4) Aantal parameters dat verwijderd moeten worden uit de stack nadat de method uitgevoerd is.
5) De parameters die doorgegeven moeten worden naar de method die aangeroepen wordt, in dit geval een parameter die aangeeft of het licht aan of uit moet zijn, en het nummer van het licht.
Lichtnummers: 0 voorzijde links | 1 voorzijde rechts | 3 achterzijde beide
Standaard kun je de achterlichten niet apart aan- of uitzetten. Maar dit kan opgelost worden door:
Dit heb ik gevonden in de source van mtasa. Er staat bij dat dit een bug is in het spel, maar ik denk dat het ook zou kunnen dat het gewoon iets onafgewerkts is (in de video kun je namenlijk zien dat de achterlichten van hotring racer A nog steeds niet apart werken).
Edit:
Nu hebben we volgende lichtnummers: 0 voorzijde links | 1 voorzijde rechts | 2 achterzijde links | 3 achterzijde rechts
Om hiermee gemakkelijk te kunnen werken had ik het idee om verschillende stukjes code te maken waar we naartoe kunnen gosub'en om de voorlichten of achterlichten te kunnen sturen.
Dus om bijvoorbeeld het linkervoorlicht te laten werken en het rechtervoorlicht te laten doven kunnen we dit met 1 lijntje doen:
Nu kun je even uitblazen want hier is het moeilijkste gedeelte al achter de rug
Variabelen toekennen
Hier ga ik plaatsen welk variabelen we voor wat gaan gebruiken, dit kan handig zijn om op terug te vallen als je even niet meer weet wat je aan het doen bent of als je de code na een lange tijd terugziet.
Alle andere nummers die je eventueel tegenkomt, zijn tijdelijke variablen.
32@ en 33@ zijn speciale timer-variabelen, deze worden elke milliseconde verhoogd met 1. Dit kan handig zijn als je een missie hebt met tijdsbeperking of als je een vertraging nodig hebt zoals hier: anders zou het misschien zo snel gaan dat je het niet deftig kan zien. Soms is dit ook te verkiezen boven een wait, want bij een wait kun je namelijk niets anders doen, maar als je een timer variabele gebruikt kun je bijvoorbeeld ondertussen nog kijken of de speler op een bepaalde toets drukt voor een menu te tonen.
Incar subroutine
Dit is een subroutine die gaat checken of de speler in een auto zit. Als dit zo is, zetten we 4@ op 1 en 9@ naar de damage handler pointer. Dit kunnen we dan aanroepen door een simpele gosub te gebruiken.
4@ geeft aan of de speler in een auto zit
9@ wijst naar de damage handler van de auto (zie eerste puntje: belangrijkste code + uitleg)
code map
Toggle subroutine
Deze subroutine zal de staat verwisselen. Als het effect niet actief is, dan deze aanzetten, tekst tonen, variables resetten en een geluidje afspelen. Anders uitzetten, tekst tonen en een geluidje afspelen.
1@ geeft aan of het effect actief is.
code map
Pattern control subroutines
Hier gaan we de patronen aansturen. Dit is het masterplan:
in 5@ zit de zgn 'pattern index', deze geeft aan in hoeverre het patroon zit. Dit zal van 0 tot 23 lopen (dus 24 verschillende staten). Afhankelijk van deze pattern index zullen we de staat van lichten veranderen. Zowel de voorlichten als achterlichten zullen een eigen patroon hebben.
De patronen die ik ga gebruiken staan in commentaar. L = links en R = rechts, - wil zeggen alles uit. Dan moeten we naar de juiste labels springen om de lichten veranderen enkel als het nodig is. Dus bv als er een - na een - komt hoeft er niets te gebeuren want de lichten zitten al in die staat.
Dit kan gemakkelijk geïmplementeerd worden door jump tables. Voor de mensen die al wat van programmeren kennen: dit lijkt goed op een switch statement.
Deze code wil zeggen dat we de waarde van 5@ zullen bekijken & er zijn 16 verschillende waardes waarvoor we kunnen jumpen naar een label. Als de waarde niet overeenkomt met een van die ingestelde waardes, gebruik de default jump (-1) en die gaat naar :R (dit is gewoon een label met een return statement erna). De rest van de waardes staan na elkaar. Bv als 5@ 0 is, jump naar :FL, bij 1 jump naar :FN etc etc.
In 0871 kunnen we 7 waardes zetten, hiermee hebben we echter niet genoeg maar gelukkig is er nog 0872 waarmee we de jump table kunnen uitbreiden. Hiermee hebben we net genoeg voor dit patroon, maar je kunt de jump table meerdere keren uitbreiden.
De labels zijn van de stukjes die ik in het begin heb gezet (belangrijkste code + uitleg).
Merk op dat er hier op het einde allemaal -1 @R staat. Dit is omdat die opcode zoveel parameters verwacht, en we kunnen die niet leeglaten dus zetten we er meestal hetzelfde als bij de default case.
Deze zullen we ook oproepen met gosub.
Hoofdcode
Nu hebben we alle subroutines en kunnen we beginnen aan de main code.
:ELS_START duidt het begin aan van de loop. Hier staat er ook een wait 0 omdat dit een oneindige loop is en het spel kan anders niets anders doen.
pseudocode
code
code map
Patroon aansturen
Bij :ELS_START_PATTERN gaan we het patroon aansturen. Hier zullen we een vertraging insteken zodat het patroon niet te snel zal gaan. Zoals eerder vermeld gaan we hiervoor timer 33@ gebruiken. 5@ geeft de index aan van het patroon.
pseudocode
code
code map
Finito
En dat is het
Volledige code:
Volledige code map:
In SA-MP zullen de andere spelers het enkel kunnen zien als het nacht is, aangezien de lichten zogezegd niet aanstaan tijdens de dag. Ook zullen de achterlichten voor de andere spelers ofwel beide aan of uit zijn, tenzij ze ook deze mod hebben of een andere die de waarde aanpast die dit fixt.
Nu kun je het natuurlijk uitbreiden, misschien meerdere patronen, een mooi menu'tje?
Edits:
28/06/2015 quote van @Big Boss mbt hotring racer bijgezet
14/04/2017 fix niet-werkende incar subroutine.. oeps (+ fix attachments)
Bewerkt: door robin_be