Actors scripten (GTA San Andreas)

Er zijn twee soorten actors: de gewone actors en de special actors. De gewone actors zijn over het algemeen de standaard voetgangers, maar ook bijvoorbeeld de overheids-actors (zoals de politie) vallen hieronder. De special actors zijn, zoals de naam al zegt, speciaal. Ze lopen niet rond. Voorbeelden van special actors zijn Sweet en Catalina.

Actors spawnen

Gewone actors

De gewone actors zijn vrij eenvoudig te maken, ze worden ongeveer hetzelfde geladen als een gewoon model (zoals bijvoorbeeld wapens). Bij de zogenaamde special actors is het wat lastiger, maar hier komen we later op terug. Eerst gaan we de gewone actors_modellen laden (en controleren of ze geladen zijn), spawnen, en vervolgens natuurlijk ook weer unloaden.

We beginnen in de "stripped" code, dat is een code die helemaal clean is. Je kunt dus niets doen, alleen wat rondlopen en autorijden. Dit is natuurlijk ideaal voor een nieuwe mod. Een actor is niets anders als een karakter in het spel, op welke manier dan ook (dus bijvoorbeeld Sweet, maar ook de voetgangers).

Allereerst moet je het principe kennen. Je moet een model van de actor (actor_model) laden, vervolgens kijken of hij geladen is (zo niet, wachten tot hij wél geladen is), daarna de actor spawnen en tot slot het model weer unloaden.

Eerst gaan we dus de actor loaden:

// Load models
0247: load_model #BFYST
038B: load_requested_models

Achter // schrijf je een notitie, die // zorgt ervoor dat het systeem deze regel overslaat en er niet naar kijkt. Dit is dus alleen maar als verduidelijking voor de modder zelf. De regel "Load_model" daar geef je aan welk model je hebt. In deze tutorial is er gekozen voor het model BFYST, maar daar zijn allemaal andere voor te gebruiken. De derde regel zorgt ervoor dat het model echt geladen wordt.

Vervolgens moet je er, zoals gezegd, voor zorgen dat het model ook echt geladen is:

:MODEL_LOAD
00D6: if 
8248:   not model #BFYST available 
004D: jump_if_false @MODEL_SPAWN 
0001: wait 0 ms 
0002: jump @MODEL_LOAD 

:MODEL_SPAWN

Met deze code kijk je dus of het model geladen is, zo niet, dan begint hij opnieuw. Je begint met het aanmaken van een nieuw label. Het maakt natuurlijk niet uit of hoe je die label noemt, maar een duidelijke naam maakt het later makkelijker om je labels terug te vinden. In deze tutorial heet het label MODEL_LOAD.

Om het vervolg uit te leggen moet je eerst weten wat een if-structuur is. If betekent als/indien. Dus if ... jump @ MODEL_LOAD, betekent indien ... gebeurt, spring dan naar het label :MODEL_LOAD. In deze contekst betekent het dus: indien (regel 2) het model BFYST niet beschikbaar is (regel 3), spring dan naar het label MODEL_LOAD (regel 5).

Er zit nog een regel tussen, namelijk "jump_if_false @MODEL_SPAWN". De “jump_if_false" zorgt ervoor dat op het moment dat de if niet waar is (in dit geval dus dat het model wel geladen is), er naar een ander label (MODEL_SPAWN) gesprongen wordt.

Zo hebben we dus al 2 van de 4 dingen gedaan. Nu gaan we het model laten spawnen: de actor staat.

:MODEL_SPAWN
10@ = Actor.Create(CIVFEMALE, #BFYST, 0.0, 0.0, 0.0)
Actor.Angle(10@) = 318.9705

De "10@" is een lokale variabele, het maakt dus niet uit welk getal je neemt. Het moet echter wel onder de 33 zijn, want dat is het maximum binnen een thread (bij missies kunnen er meer zijn). Dan ga je die variabele definiëren. Actor.Create lijkt me duidelijk... Dan tussen haakjes, zie je 5 dingen die je in moet vullen. Allereerst het type ped, in mijn geval is het CIVFEMALE. Dan de naam van de ped weer, met een # ervoor (dus #BFYST). Vervolgens de 3 coördinaten: x, y en z. De Actor.Angle is de hoek waarin de ped staat. Het westen is 0.0. Wil je hem naar het oosten hebben staan, moet je de Angle dus 180.0 hebben.

Tot slot moet je ook in je code nog verwerken dat je het model unload:

0249: release_model #BFYST

Dus de volledige code is:

 // Load models
 0247: load_model #BFYST
 038B: load_requested_models
 
 :MODEL_LOAD
 00D6: if 
 8248:   not model #BFYST available 
 004D: jump_if_false @MODEL_SPAWN 
 0001: wait 0 ms 
 0002: jump @MODEL_LOAD 
 
 :MODEL_SPAWN
 10@ = Actor.Create(CIVFEMALE, #BFYST, 0.0, 0.0, 0.0)
 
 //Hier komt wat je met je actor wilt doen
 
 0249: release_model #BFYST

Met de Ped Editor kan je opzoeken welke ped je wilt hebben. Je ziet zo gelijk een beeld van de ped ingame, je ziet de naam van de ped én je ziet de groep, kortom: alles wat je nodig hebt staat erin. De coördinaten kan je opzoeken via de San Andreas Place Manager. Je kunt ook in Sanny Builder zelf kijken welke coördinaten je op dat moment ingame hebt, door naar "tools" te gaan, dan naar IDE tools en tot slot op "Coords manager".

Special actors

Special actors zijn iets moeilijker. Je hebt namelijk maar 10 slotjes voor special actors. Het is te vergelijken met de 8 slotjes waarin je je savegame zet: je kunt er altijd maar 8 tegelijk bewaren, en op het moment dat je andere savegames wilt hebben moet je er verwijderen om vervolgens die te kunnen plaatsen. Zo werkt het ook met de special actors. Een lijst met alle actors die tot de special actors behoren, kan je vinden bij de SCM Documentatie bank van Sanny Builder. Ga naar Help >> Contents >> SCM Documentation >> GTA SA >> Special Actors.

Als je het principe van de special actors snapt, is het eigenlijk zo moeilijk niet meer en lijkt het wel op een gewone actor (maar met een iets andere code). Opnieuw moet je goed onthouden: model loaden, checken of model geladen is, actor spawnen, model unloaden.

We pakken als voorbeeld Catalina. Je ziet in de lijst uit de documentatie bank dat zij de naam 'CAT' in de code heeft. Laten we het model eerst maar gaan laden:

 // Load models
 023C: load_special_actor 'CAT' as 1 // models 290-299
 038B: load_requested_models

De special actor Catalina laden. "as 1" betekent in slotje 1, dus kan je naast deze nog 9 anderen loaden.

Vervolgens moeten we natuurlijk weer checken of hij geladen is:

 :MODEL_LOAD
 00D6: if or 
 823D:   not special_actor 1 loaded 
 004D: jump_if_false @MODEL_SPAWN 
 0001: wait 0 ms 
 0002: jump @MODEL_LOAD 
 
 :MODEL_SPAWN

Dit is dus bijna hetzelfde als die van de "normale" actor, dus veel uitleg is niet nodig. Alleen is het nu "not_special_actor 1 loaded" in plaats van "not model #BFYST available". In principe betekent het hetzelfde, wanneer het model voor de actor of special actor niet geladen is, jump dan naar het label MODEL_LOAD. De 1 staat in dit geval voor het nummer van het slotje.

 :MODEL_SPAWN
 009A: 10@ = create_actor_pedtype 4 model #SPECIAL01 at 0.0 0.0 0.0
 0173: set_actor #SPECIAL01 Z_angle_to 0.0

Je gebruikt #SPECIAL01 als naam voor degene die slotje 1 heeft. 4 is het pedtype. De angle is de hoek hoe hij moet staan, 0.0 is het westen.

Tot slot ook nog unloaden natuurlijk:

 0296: unload_special_actor 1

Dus weer het unloaden van het model van de special actor die in slotje 1 staat.

De volledige code:

 // Load models
 023C: load_special_actor 'CAT' as 1 // models 290-299
 038B: load_requested_models  
     
 :MODEL_LOAD
 00D6: if or 
 823D:   not special_actor 1 loaded 
 004D: jump_if_false @MODEL_SPAWN 
 0001: wait 0 ms 
 0002: jump @MODEL_LOAD 
 
 :MODEL_SPAWN
 009A: 10@ = create_actor_pedtype 4 model #SPECIAL01 at 0.0 0.0 0.0
 0173: set_actor 10@ Z_angle_to 0.0
 
 // Hier komt te staan wat je met de actor wilt doen
 
 0296: unload_special_actor 1

Volledige code

 {
   use macro (Ctrl+J) "headsa"
   to insert a file header      
 }
 {$VERSION 3.0.0000}                                                               
 
 thread 'MAIN'
  var
   $PLAYER_CHAR: Player 
  end // var
 01F0: set_max_wanted_level_to 6 
 set_wb_check_to 0 
 00C0: set_current_time 8 0 
 04E4: unknown_refresh_game_renderer_at 2488.5601 -1666.84 
 Camera.SetAtPos(2488.5601, -1666.84, 13.38)
 $PLAYER_CHAR = Player.Create(#NULL, 2488.5601, -1666.84, 13.38)
 $PLAYER_ACTOR = Actor.EmulateFromPlayer($PLAYER_CHAR)
 07AF: $PLAYER_GROUP = player $PLAYER_CHAR group
 Camera.SetBehindPlayer
 set_weather 0          
 wait 0 ms
 $PLAYER_CHAR.SetClothes("PLAYER_FACE", "HEAD", Head)
 $PLAYER_CHAR.SetClothes("JEANSDENIM", "JEANS", Legs)                          
 $PLAYER_CHAR.SetClothes("SNEAKERBINCBLK", "SNEAKER", Shoes)
 $PLAYER_CHAR.SetClothes("VEST", "VEST", Torso)
 $PLAYER_CHAR.Build
 $PLAYER_CHAR.CanMove = True
 fade 1 (out) 0 ms                     
 select_interior 0
 0629: change_stat 181 (islands unlocked) to 4
 016C: restart_if_wasted at 2027.77 -1420.52 15.99 angle 137.0 for_town_number 0
 016D: restart_if_busted at 1550.68 -1675.49 14.51 angle 90.0 for_town_number 0
 0180: set_on_mission_flag_to $ONMISSION // Note: your missions have to use the variable defined here ($ONMISSION)
 03E6: remove_text_box
 // put your create_thread commands here
 
 create_thread @MODEL
 
 // IDLE LOOP
 :leeg
 wait 500
 jump @leeg
   
 end_thread 
 
 :MODEL
 thread "MODEL"  
 
 // Load models
 0247: load_model #BFYST
 038B: load_requested_models
 
 :MODEL_LOAD
 00D6: if
 8248:   not model #BFYST available
 004D: jump_if_false @MODEL_SPAWN
 0001: wait 0 ms
 0002: jump @MODEL_LOAD
 
 :MODEL_SPAWN
 10@ = Actor.Create(CIVFEMALE, #BFYST, 2488.5601, -1680.84, 13.3438 )
 
 //Hier komt wat je met je actor wilt doen
 
 0249: release_model #BFYST
 
 end_thread

Actors in een script gebruiken

Je kunt de actor vele dingen laten doen, zoals bijvoorbeeld in de auto laten stappen of naar jou laten schieten. Maar eerst moeten ze gespawnd zijn, voordat je die dingen kunt gaan toevoegen. Daarom is het essentieel om dit eerst te weten.

In dit tweede deel van de tutorial gaan we de code waarmee me in deel 1 gestopt zijn iets verder uitbreiden. We geven de actor een wapen en stellen wat eigenschappen in. De speler krijgt ook een wapen. Om het enigszins leuk te maken moeten de speler en de actor elkaar vermoorden. Als je de actor vermoordt krijg je een muziekje, een "mission passed"-tekst en 25.000 dollar.

Wapens

Om een wapen aan een actor te geven, moet je eerst het wapen-model laden. Net zoals je in deel 1 het actor-model van een actor moest laden voordat je het kunt spawnen. Gelukkig is het laden van een wapen model identiek aan het laden van een actor-model. voor het laden van het actor model hadden we de volgende code

 // Load models
 0247: load_model #BFYST
 038B: load_requested_models
 
 :MODEL_LOAD
 00D6: if
 8248:   not model #BFYST available
 004D: jump_if_false @MODEL_SPAWN
 0001: wait 0 ms
 0002: jump @MODEL_LOAD
 
 :MODEL_SPAWN  

Dit stuk code gaan we uitbreiden voor het laden van de modellen van 3 wapens: De desert_eagle, de rocket-launcher en de m4. In de help-files van sannybuilder zoeken we de juiste namen op: Help->SCM Documentation->GTA SA->Weapon numbers

We zoeken daar de wapennummers en de modelnamen van de wapens die we willen gebruiken:

  • desert-eagle 24 #DESERT_EAGLE
  • rocket-launcher 35 #ROCKETLA
  • M4 31 #M4

We breiden nu de bovenstaande code uit met de modelnamen van deze wapens, op deze manier:

 // Load models
 0247: load_model #BFYST
 0247: load_model #rocketla
 0247: load_model #desert_eagle 
 0247: load_model #m4 
 038B: load_requested_models
 
 :MODEL_LOAD
 00D6: if or
 8248:   not model #BFYST available
 8248:   not model #rocketla available 
 8248:   not model #desert_eagle available 
 8248:   not model #m4 available 
 004D: jump_if_false @MODEL_SPAWN
 0001: wait 0 ms
 0002: jump @MODEL_LOAD
 
 :MODEL_SPAWN

Naast het actor model wordt nu dus ook het laden van de wapen modellen aangevraagd. En we wachten daaronder net zolang, tot alle 4 modellen geladen zijn.

Nu gaan we de wapens uitdelen. Om te beginnen geven we de speler een rocket-launcher en een desert_eagle

 01B2: give_actor $PLAYER_ACTOR weapon 35 ammo 10 // Load the weapon model before using this
 01B2: give_actor $PLAYER_ACTOR weapon 24 ammo 30000 // Load the weapon model before using this
 01B9: set_actor $PLAYER_ACTOR armed_weapon_to 24

Hier komen de wapennummers om de hoek kijken die we hierboven opgezocht hebben.

We geven de speler een rocket-launcher (35) met 10 raketten en een desert-eagle(24) met 30.000 kogels. De speler heeft nu twee wapens, maar omdat hij er maar 1 tegelijk kan gebruiken moeten we er ook nog 1 in zijn handen stoppen en dat doen we met het onderste commando.

De speler is bewapend, nu de actor nog.

 01B2: give_actor 10@ weapon 31 ammo 30000 // Load the weapon model before using this
 01B9: set_actor 10@ armed_weapon_to 31

De actor krijgt dus een m4 (31) met 30.000 kogels, en die geven we hem ook direct in de handen.

Eigenschappen

Nu hebben we dus een bewapende speler en een bewapende actor. Om wat leven in de brouwerij te krijgen geven de actor de opdracht om de speler te doden. Om het iets moeilijker te maken stellen we nog een paar eigenschappen in.

 05E2: AS_actor 10@ kill_actor $PLAYER_ACTOR

Deze code zorgt dat zij de speler probeert te doden.

 actor.WeaponAccuracy(10@)= 90

Deze code zorgt dat zij nauwkeuriger kan richten met z'n wapen dan normaal.

 actor.Health(10@) = 2000

Deze code zorgt zij een extra hoog health niveau heeft, dus niet zo snel dood is.

 0350: toggle_actor 10@ maintain_position_when_attacked 1

Deze code zorgt dat zij niet bang wegloopt als hij wordt aangevallen.

Mini-missie

Alles staat klaar voor een vechtpartij. Nu moeten we dus wachten hoe het afloopt. Mocht de speler geraakt worden, dan spawned ie vanzelf opnieuw bij het ziekenhuis, en kan hij opnieuw gaan vechten (hoewel hij geen wapens meer heeft). Het is dus eigenlijk wachten op het moment dat de actor gedood wordt.

Dat doen we met de volgende code

 repeat
  wait 0 ms 
 until actor.Dead(10@)

We wachten dus net zolang tot de actor dood is.

Beloning

Daarna geven we een melding en voor de aardigheid een beloning

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

De eerste regel speelt een overwinningsmuziekje terwijl de tweede regel op het scherm meld dat de missie gelukt is. Als beloning geeft de derde regel de speler een som van 25000 dollar.

Het enige dat we hierna nog moeten doen is het unloaden van de models die we gebruikt hebben. Dit gaat op dezelfde manier als met de actor model, dus

 0249: release_model #BFYST
 0249: release_model #rocketla
 0249: release_model #desert_eagle
 0249: release_model #m4

Volledige code

 {
 use macro (Ctrl+J) "headsa"
 to insert a file header
 }
 {$VERSION 3.0.0000}
 
 thread 'MAIN'
 var
 $PLAYER_CHAR: Player
 end // var
 01F0: set_max_wanted_level_to 6
 set_wb_check_to 0
 00C0: set_current_time 8 0
 04E4: unknown_refresh_game_renderer_at 2488.5601 -1666.84
 Camera.SetAtPos(2488.5601, -1666.84, 13.38)
 $PLAYER_CHAR = Player.Create(#NULL, 2488.5601, -1666.84, 13.38)
 $PLAYER_ACTOR = Actor.EmulateFromPlayer($PLAYER_CHAR)
 07AF: $PLAYER_GROUP = player $PLAYER_CHAR group
 Camera.SetBehindPlayer
 set_weather 0
 wait 0 ms
 $PLAYER_CHAR.SetClothes("PLAYER_FACE", "HEAD", Head)
 $PLAYER_CHAR.SetClothes("JEANSDENIM", "JEANS", Legs)
 $PLAYER_CHAR.SetClothes("SNEAKERBINCBLK", "SNEAKER", Shoes)
 $PLAYER_CHAR.SetClothes("VEST", "VEST", Torso)
 $PLAYER_CHAR.Build
 $PLAYER_CHAR.CanMove = True
 fade 1 (out) 0 ms
 select_interior 0
 0629: change_stat 181 (islands unlocked) to 4
 016C: restart_if_wasted at 2027.77 -1420.52 15.99 angle 137.0 for_town_number 0
 016D: restart_if_busted at 1550.68 -1675.49 14.51 angle 90.0 for_town_number 0
 0180: set_on_mission_flag_to $ONMISSION // Note: your missions have to use the variable defined here ($ONMISSION)
 03E6: remove_text_box
 // put your create_thread commands here
 
 create_thread @MODEL
 
 // IDLE LOOP
 :leeg
 wait 500
 jump @leeg
 
 end_thread
 
 :MODEL
 thread "MODEL"
 
 // Load models
 0247: load_model #BFYST
 0247: load_model #rocketla
 0247: load_model #desert_eagle 
 0247: load_model #m4 
 038B: load_requested_models
 
 :MODEL_LOAD
 00D6: if or
 8248:   not model #BFYST available
 8248:   not model #rocketla available 
 8248:   not model #desert_eagle available 
 8248:   not model #m4 available 
 004D: jump_if_false @MODEL_SPAWN
 0001: wait 0 ms
 0002: jump @MODEL_LOAD
 
 :MODEL_SPAWN
 10@ = Actor.Create(CIVFEMALE, #BFYST, 2488.5601, -1680.84, 13.3438 )
 actor.WeaponAccuracy(10@)= 90
 actor.Health(10@) = 2000
 0350: toggle_actor 10@ maintain_position_when_attacked 1 
 05E2: AS_actor 10@ kill_actor $PLAYER_ACTOR 
 
 // geef de actor een M4
 01B2: give_actor 10@ weapon 31 ammo 30000 // Load the weapon model before using this
 01B9: set_actor 10@ armed_weapon_to 31
   
 //  Geef de speler een desert eagle en een rocket-launcher, en maak de desert-eagle het actieve wapen
 01B2: give_actor $PLAYER_ACTOR weapon 35 ammo 10 // Load the weapon model before using this
 01B2: give_actor $PLAYER_ACTOR weapon 24 ammo 30000 // Load the weapon model before using this
 01B9: set_actor $PLAYER_ACTOR armed_weapon_to 24
   
 repeat
  wait 0 ms 
 until actor.Dead(10@)
 
 0394: play_music 1 
 01E3: show_text_1number_styled GXT 'M_PASS' number 10000 time 5000 style 1  // MISSION PASSED!~n~~w~$~1~
 Player.Money($PLAYER_CHAR) += 25000
   
 0249: release_model #BFYST
 0249: release_model #rocketla
 0249: release_model #desert_eagle
 0249: release_model #m4
 
 end_thread

Externe links