Posted: Mon, 4.11.2002, 10.23
Joo, saan päähäni kirjotella tänne vähän juttuja tuosta OFP:n tehtäväeditoinnista moninpelikäyttöön...
Triggerit
Triggereiden toiminta moninpelissä on vähän erilaista kun mitä yleensä luullaan, mistä johtuu että moni mappi "desynkkaa" eli eri pelaajilla tapahtuu eri juttuja. Tämä johtuu siitä, että kuten kaikki muukin OFP:ssä, myös triggerit ajetaan joka pelaajalla "lokaalisti" eli jokaisella pelaajalla erikseen. Esimerkiksi seuraavanlainen skenaario:
Triggeri "east present"
Pelaaja X = west ukko
Pelaaja Y = east ukko
Kun pelaaja Y kävelee tuon triggerin päälle, ei hänen koneensa lähetä mitään sen erikoisempaa tietoa triggerin laukeamisesta pelaajalle X. Mutta normaalissa tilanteessa triggeri laukeaa myös pelaajalla X, koska pelaaja Y:n peliukko kuitenkin myös hänen koneellaan seisoo triggerin sisällä, jolloin se laukeaa myös hänella.
Mutta, jos juuri tuohon triggerin ylikävelemiseen sattuu tulemaan lagipiikki, pelaaja Y/X muuten vain lagaa, tai nuo pelaajat on hirveän kaukana toisistaan niin saattaa käydä niin että pelaaja X:n silmissä pelaaja Y warppaa tuon triggerin yli eikä se X:llä koskaan laukea, vaikka Y:llä se niin tekeekin. Eli näin sitten noilla kahdella ukolla on täysin eri pelitilanne.
Tämän korjaamiseksi kaikkia kriittisiä triggereitä varten täytyykin tehdä kaksi triggeriä esim. seuraavanlaisesti:
Triggeri "east present", johon "statement" kohtaan (jossa siis normaalisti olisi joku tapahtuma, vaikkapa hint "wii") laitetaankin esimerkiksi: Triggeri1Lauennut = true;publicvariable "Triggeri1Lauennut";
Tämä siis asettaa muuttujan "Triggeri1Lauennut" arvoksi "true". Mutta tämä ei yksin vielä auta mitään, vaan "publicvariable" on taikasana, joka lähettää tämän "Triggeri1Lauennut" muuttujan "true" arvon joka ikiselle pelissä mukana olevalle pelaajalle. Eli siis vaikka tuo triggeri olisi lauennut vain yhdellä pelaajalla, muiden silmissä hänen warpanneen sen yli, lähettää hänen koneensa kaikille muille tuon Triggeri1Lauennut muuttujan tilan muille, jonka jälkeen voidaankin tehdä toinen triggeri, jonka "condition" kenttään laitetaan "Triggeri1Lauennut" ja sen statement kenttään tuo hint "wii". Tämä triggeri sitten laukeaa taas joka koneella takuuvarmasti, koska heillä kaikilla on tuo Triggeri1Lauennut on sama.
Scriptit
Scriptitkin (exec, addaction) ajetaan kaikki lokaalisti, joka ei yleensä vaikuta paljoa mutta niissäkin, varsinkin addActionia käyttäessä on muistettava joitakin juttuja.
Eli lagista, koneiden eri nopeuksista, ym. sekoista johtuen scriptit harvoin alkavat/päättyvät täysin samaan aikaan moninpelissä. Tästä siis johtuu, että esimerkiksi joskus moninpelimappien introjen aikana jotkut ukot saattavat jo lähteä kävelemään ympäriinsä kun itse vielä katselee introa. Tälle ei mitään sen erityisemppä fiksiä ole mahdollista tehdä.
addActionin kanssa täytyy erityisesti huomioida lokaalisti ajettavuus, sillä sitä käyttäessä scripti ajetaan _vain_ sillä pelaajalla joka tuon kyseisen actionin "laukaisi". Eli jos addActionin scriptissä tekee jotain, minkä haluaa tapahtuvan kaikilla muillakin (esim. tekstin näyttäminen) täytyy taas käyttää samanlaista publicvariable kikkailua kun triggereidenkin kanssa.
player
OFP:ssä on vakiona muuttuja "player" joka osoittaa aina paikalliseen pelaajaan. Tämän avulla voi tehdä kaikenlaista hauskaa, ja se voi myös helpottaa montaa asiaa. Eli esimerkiksi jos halutaan lisätä jokaiselle pelaajalle M16 ase, olisi "normaali" lähestymistapa about seuraavanlainen:
p1 addweapon "M16";
p2 addweapon "M16";
p3 addweapon "M16";
p4 addweapon "M16";
p5 addweapon "M16";
...
Ja näitähän ei kukaan jaksa kirjoitella, joten kun tehdäänkin sen sijaan näin:
player addweapon "M16"
jonka siis jokaisen pelaajan kone ajaa itse omalla koneellaan, ja koska heilla kaikilla "player" on oma itsensä, jokainen antaa itse itselleen M16 aseen, eli lopputulos on sama kun ylläolevassa scriptissä, mutta paljon helpommin. Tässä tosin kannattaa muistaa että AI ryhmänjäsenille tuollainen ei lisäisi mitään.
Myös addActionin kanssa playerin käyttö on hyödyllistä. Eli jos mukana taas olisi pelaajat "p1", "p2", "p3" jne. ja heille kailille haluttaisiin addActionia käyttäen lisätä vaikkapa "Suicide" action, olisi yleinen lähestymistapa laittaa jokaisen heidän initiin 'this addaction["suicide","suicide.sqs]' joka sinällään toimii, muttei aivan halutunlaisesti. Eli koska taas jokainen pelaaja ajaa kaikki nämä scriptit omalla koneellaan, käy niin, että esimerkiksi "p1" pelaajan silmissä myös "p2" pelaajaan on lisätty tuo actioni. Nyt kun pelaaja P1 kävelee P2:n luo, tulee hänen valikkoonsa kaksi "suicide" actionia, hänessä itsessään oleva ja P2:ssa oleva.
Tämä on taas yksinkertaista korjata tekemällä
player addAction["suicide","suicide.sqs]
joka siis taas lisää jokaisella pelaajalla lokaalisti itseensä tuon actionin. Mutta tämä täytyy tehdä _vain kerran_, eli ei laittamalla sitä jokaisen p1,p2,p3 ukon initiin (jolloin siis jokainen lisäisi sen itseensä monta kertaa) vaan vaikkapa init.sqs tiedostoon, tai triggeriin joka laukeaa heti alussa.
"liidujen" siirtyminen, missionin lopetus
Kuten varmaan monet ovat huomanneet, ryhmänjohtajan kuollessa moninpelissä johtajan hommat eivät siirry automaattisesti seuraavalle, johon täytyykin tehdä simppeli "workaround" seuraavanlaisella triggerillä:
condition: not alive (leader group player)
statement: [(leader group player)] join grpNull
ja tyypiksi "repeatedly". Tämä triggeri laukeaa aina, kun pelaajan ryhmän leader kuolee, ja heittää hänet siitä ryhmästä ulos (siirtää grpNull:iin). "Countdown" aikaa kannattaa ehkä laittaa sekunti tai pari.
"Klassinen" ongelma varsinkin coop tehtävissä on, miten saada tehtävä loppumaan kun kaikki pelaajat on kuolleet. Simppeli ratkaisu on tehdä erittäin iso "not present" triggeri, joka taas ei toimi mikäli mapissa on AI:n ohjastamia ukkoja jotka on samalla puolella kun pelaaja... Itsekään en tähän ongelmaan hirveän toimivaa ratkaisua teidä, mutta yksi tapa ainakin on seuraava:
1) init.sqs:ään tms. laitetaan 'kruuppi = group player'
2) Triggeri, jonka "condition" kenttään '(count units kruuppi) < 1'
3) Yllä mainittu liidujensiirtymistriggeri
Itse en tätä ole vielä testannut, mutta periaatteessa sen pitäisi toimia, koska liidujensiirymisscripti heittelee pelaajia ulos "kruuppi" ryhmästä, eikä heitä ole siellä enää yhtään jäljellä kun kaikki on kuolleet. Tämä ratkaisu ei taas toimi mikäli mukana on useampi grouppi...
Semmosta, toivottavasti jollekin jotain apua
-Kegetys :PP
Triggerit
Triggereiden toiminta moninpelissä on vähän erilaista kun mitä yleensä luullaan, mistä johtuu että moni mappi "desynkkaa" eli eri pelaajilla tapahtuu eri juttuja. Tämä johtuu siitä, että kuten kaikki muukin OFP:ssä, myös triggerit ajetaan joka pelaajalla "lokaalisti" eli jokaisella pelaajalla erikseen. Esimerkiksi seuraavanlainen skenaario:
Triggeri "east present"
Pelaaja X = west ukko
Pelaaja Y = east ukko
Kun pelaaja Y kävelee tuon triggerin päälle, ei hänen koneensa lähetä mitään sen erikoisempaa tietoa triggerin laukeamisesta pelaajalle X. Mutta normaalissa tilanteessa triggeri laukeaa myös pelaajalla X, koska pelaaja Y:n peliukko kuitenkin myös hänen koneellaan seisoo triggerin sisällä, jolloin se laukeaa myös hänella.
Mutta, jos juuri tuohon triggerin ylikävelemiseen sattuu tulemaan lagipiikki, pelaaja Y/X muuten vain lagaa, tai nuo pelaajat on hirveän kaukana toisistaan niin saattaa käydä niin että pelaaja X:n silmissä pelaaja Y warppaa tuon triggerin yli eikä se X:llä koskaan laukea, vaikka Y:llä se niin tekeekin. Eli näin sitten noilla kahdella ukolla on täysin eri pelitilanne.
Tämän korjaamiseksi kaikkia kriittisiä triggereitä varten täytyykin tehdä kaksi triggeriä esim. seuraavanlaisesti:
Triggeri "east present", johon "statement" kohtaan (jossa siis normaalisti olisi joku tapahtuma, vaikkapa hint "wii") laitetaankin esimerkiksi: Triggeri1Lauennut = true;publicvariable "Triggeri1Lauennut";
Tämä siis asettaa muuttujan "Triggeri1Lauennut" arvoksi "true". Mutta tämä ei yksin vielä auta mitään, vaan "publicvariable" on taikasana, joka lähettää tämän "Triggeri1Lauennut" muuttujan "true" arvon joka ikiselle pelissä mukana olevalle pelaajalle. Eli siis vaikka tuo triggeri olisi lauennut vain yhdellä pelaajalla, muiden silmissä hänen warpanneen sen yli, lähettää hänen koneensa kaikille muille tuon Triggeri1Lauennut muuttujan tilan muille, jonka jälkeen voidaankin tehdä toinen triggeri, jonka "condition" kenttään laitetaan "Triggeri1Lauennut" ja sen statement kenttään tuo hint "wii". Tämä triggeri sitten laukeaa taas joka koneella takuuvarmasti, koska heillä kaikilla on tuo Triggeri1Lauennut on sama.
Scriptit
Scriptitkin (exec, addaction) ajetaan kaikki lokaalisti, joka ei yleensä vaikuta paljoa mutta niissäkin, varsinkin addActionia käyttäessä on muistettava joitakin juttuja.
Eli lagista, koneiden eri nopeuksista, ym. sekoista johtuen scriptit harvoin alkavat/päättyvät täysin samaan aikaan moninpelissä. Tästä siis johtuu, että esimerkiksi joskus moninpelimappien introjen aikana jotkut ukot saattavat jo lähteä kävelemään ympäriinsä kun itse vielä katselee introa. Tälle ei mitään sen erityisemppä fiksiä ole mahdollista tehdä.
addActionin kanssa täytyy erityisesti huomioida lokaalisti ajettavuus, sillä sitä käyttäessä scripti ajetaan _vain_ sillä pelaajalla joka tuon kyseisen actionin "laukaisi". Eli jos addActionin scriptissä tekee jotain, minkä haluaa tapahtuvan kaikilla muillakin (esim. tekstin näyttäminen) täytyy taas käyttää samanlaista publicvariable kikkailua kun triggereidenkin kanssa.
player
OFP:ssä on vakiona muuttuja "player" joka osoittaa aina paikalliseen pelaajaan. Tämän avulla voi tehdä kaikenlaista hauskaa, ja se voi myös helpottaa montaa asiaa. Eli esimerkiksi jos halutaan lisätä jokaiselle pelaajalle M16 ase, olisi "normaali" lähestymistapa about seuraavanlainen:
p1 addweapon "M16";
p2 addweapon "M16";
p3 addweapon "M16";
p4 addweapon "M16";
p5 addweapon "M16";
...
Ja näitähän ei kukaan jaksa kirjoitella, joten kun tehdäänkin sen sijaan näin:
player addweapon "M16"
jonka siis jokaisen pelaajan kone ajaa itse omalla koneellaan, ja koska heilla kaikilla "player" on oma itsensä, jokainen antaa itse itselleen M16 aseen, eli lopputulos on sama kun ylläolevassa scriptissä, mutta paljon helpommin. Tässä tosin kannattaa muistaa että AI ryhmänjäsenille tuollainen ei lisäisi mitään.
Myös addActionin kanssa playerin käyttö on hyödyllistä. Eli jos mukana taas olisi pelaajat "p1", "p2", "p3" jne. ja heille kailille haluttaisiin addActionia käyttäen lisätä vaikkapa "Suicide" action, olisi yleinen lähestymistapa laittaa jokaisen heidän initiin 'this addaction["suicide","suicide.sqs]' joka sinällään toimii, muttei aivan halutunlaisesti. Eli koska taas jokainen pelaaja ajaa kaikki nämä scriptit omalla koneellaan, käy niin, että esimerkiksi "p1" pelaajan silmissä myös "p2" pelaajaan on lisätty tuo actioni. Nyt kun pelaaja P1 kävelee P2:n luo, tulee hänen valikkoonsa kaksi "suicide" actionia, hänessä itsessään oleva ja P2:ssa oleva.
Tämä on taas yksinkertaista korjata tekemällä
player addAction["suicide","suicide.sqs]
joka siis taas lisää jokaisella pelaajalla lokaalisti itseensä tuon actionin. Mutta tämä täytyy tehdä _vain kerran_, eli ei laittamalla sitä jokaisen p1,p2,p3 ukon initiin (jolloin siis jokainen lisäisi sen itseensä monta kertaa) vaan vaikkapa init.sqs tiedostoon, tai triggeriin joka laukeaa heti alussa.
"liidujen" siirtyminen, missionin lopetus
Kuten varmaan monet ovat huomanneet, ryhmänjohtajan kuollessa moninpelissä johtajan hommat eivät siirry automaattisesti seuraavalle, johon täytyykin tehdä simppeli "workaround" seuraavanlaisella triggerillä:
condition: not alive (leader group player)
statement: [(leader group player)] join grpNull
ja tyypiksi "repeatedly". Tämä triggeri laukeaa aina, kun pelaajan ryhmän leader kuolee, ja heittää hänet siitä ryhmästä ulos (siirtää grpNull:iin). "Countdown" aikaa kannattaa ehkä laittaa sekunti tai pari.
"Klassinen" ongelma varsinkin coop tehtävissä on, miten saada tehtävä loppumaan kun kaikki pelaajat on kuolleet. Simppeli ratkaisu on tehdä erittäin iso "not present" triggeri, joka taas ei toimi mikäli mapissa on AI:n ohjastamia ukkoja jotka on samalla puolella kun pelaaja... Itsekään en tähän ongelmaan hirveän toimivaa ratkaisua teidä, mutta yksi tapa ainakin on seuraava:
1) init.sqs:ään tms. laitetaan 'kruuppi = group player'
2) Triggeri, jonka "condition" kenttään '(count units kruuppi) < 1'
3) Yllä mainittu liidujensiirtymistriggeri
Itse en tätä ole vielä testannut, mutta periaatteessa sen pitäisi toimia, koska liidujensiirymisscripti heittelee pelaajia ulos "kruuppi" ryhmästä, eikä heitä ole siellä enää yhtään jäljellä kun kaikki on kuolleet. Tämä ratkaisu ei taas toimi mikäli mukana on useampi grouppi...
Semmosta, toivottavasti jollekin jotain apua
-Kegetys :PP