Anonim

AIMBOT 2.0

Uuden pelin 2 jaksossa 1, noin klo 9:40, on laukaus koodista, jonka Nene on kirjoittanut:

Tässä se tekstimuodossa käännettyjen kommenttien kanssa:

// the calculation of damage when attacked void DestructibleActor::ReceiveDamage(float sourceDamage) { // apply debuffs auto resolvedDamage = sourceDamage; for (const auto& debuf:m_debufs) { resolvedDamage = debuf.ApplyToDamage(resolvedDamage); m_currentHealth -= resolvedDamage if (m_currentHealth <= 0.f) { m_currentHealth = 0.f; DestroyMe(); } } } 

Ammunnan jälkeen Umiko osoitti for-silmukalle ja sanoi, että syy miksi koodi kaatui, on se, että silmukka on ääretön.

En todellakaan tiedä C ++: ta, joten en ole varma, onko hänen sanomansa totta.

Sen perusteella, mitä näen, for-silmukka vain iteroi näyttelijän nykyisten debufien kautta. Ellei näyttelijällä ole loputtomia määriä debufeja, en usko, että siitä voi tulla ääretön silmukka.

Mutta en ole varma, koska ainoa syy siihen, että koodi on otettu, on se, että he halusivat laittaa pääsiäismunan tänne, eikö? Olisimme juuri saaneet kuvan kannettavan tietokoneen takaosasta ja kuulleet Umikon sanovan "Voi sinulla on ääretön silmukka siellä". Se, että he todella näyttivät jonkin koodin, saa minut ajattelemaan, että koodi on jotenkin pääsiäismuna.

Luodaanko koodi todella ääretön silmukka?

8
  • Todennäköisesti hyödyllinen: uusi kuvakaappaus Umikosta sanomalla "Se oli soittamalla samaan operaatioon uudestaan ​​ja uudestaan ​​", jota ei ehkä näy koodissa.
  • Vai niin! En tiennyt sitä! @AkiTanaka osa, jota katselin, sanoo "ääretön silmukka"
  • @LoganM En todellakaan ole samaa mieltä. Kyse ei ole vain siitä, että OP: lla on kysyttävää jostakin lähdekoodista, joka sattui olemaan peräisin animesta; OP: n kysymys koskee tiettyä lausuntoa noin lähdekoodin anime-hahmolla, ja animeihin liittyy vastaus, nimittäin "Crunchyroll tehty hölynpöydällä ja käännetty rivi väärin".
  • @senshin Luulen, että luet sitä, mistä haluat kysymyksen olla, eikä sitä, mitä todella kysytään. Kysymyksessä on lähdekoodia ja kysytään, generoiko se ääretön silmukka tosielämän C ++ -koodina. Uusi peli! on kuvitteellinen teos; siinä esitetyn koodin ei tarvitse olla tosielämän standardien mukainen. Se, mitä Umiko sanoo koodista, on arvovaltaisempi kuin mikään C ++ -standardi tai kääntäjä. Ylimmässä (hyväksytyssä) vastauksessa ei mainita mitään universumin sisäistä tietoa. Luulen, että aiheesta voidaan kysyä asiasta hyvä vastaus, mutta kuten se on sanottu, se ei ole.

Koodi ei ole ääretön silmukka, mutta se on vika.

On kaksi (mahdollisesti kolme) asiaa:

  • Jos debuffeja ei ole, vahinkoja ei tapahdu lainkaan
  • Liiallista vahinkoa aiheutuu, jos debuf-tiedostoja on enemmän kuin yksi
  • Jos DestroyMe () poistaa objektin välittömästi ja vielä on käsiteltäviä m_debuf-tiedostoja, silmukka suorittaa poistetun objektin ja roskakorin. Suurimmalla osalla pelimoottoreita on tuhoamisjono tämän ja muun kiertämiseksi, joten se ei välttämättä ole ongelma.

Vahinkojen tulisi olla silmukan ulkopuolella.

Tässä on korjattu toiminto:

// the calculation of damage when attacked void DestructibleActor::ReceiveDamage(float sourceDamage) { // apply debuffs auto resolvedDamage = sourceDamage; for (const auto& debuf:m_debufs) { resolvedDamage = debuf.ApplyToDamage(resolvedDamage); } m_currentHealth -= resolvedDamage if (m_currentHealth <= 0.f) { m_currentHealth = 0.f; DestroyMe(); } } 
12
  • 15 Onko koodin tarkistus käynnissä? : D
  • 4 kelluketta ovat erinomaisia ​​terveydelle, jos et ylitä arvoa 16777216 hv. Voit jopa asettaa terveyden äärettömään luoda vihollinen, jonka voit lyödä, mutta joka ei kuole, ja hyökätä yhdellä tapolla käyttämällä loputtomia vahinkoja, jotka silti eivät tappaa loputonta HP-merkkiä (INF-INF: n tulos on NaN), mutta tappaa kaiken muun. Joten se on erittäin hyödyllinen.
  • 1 @cat Monien koodausstandardien mukaan m_ etuliite tarkoittaa, että se on jäsenmuuttuja. Tässä tapauksessa jäsenmuuttuja on DestructibleActor.
  • 2 @HotelCalifornia Olen samaa mieltä siitä, että on pieni mahdollisuus ApplyToDamage ei toimi odotetulla tavalla, mutta sanoisin esimerkkitapauksessa ApplyToDamage myös täytyy muokata vaatiakseen alkuperäisen välittämistä sourceDamage samoin, jotta se voi laskea debufin oikein näissä tapauksissa. Olla ehdoton pedantti: Tässä vaiheessa dmg-tietojen tulisi olla rakenteita, jotka sisältävät alkuperäisen dmg: n, nykyisen dmg: n ja vahinkojen luonteen sekä jos debuf-tiedostoilla on esimerkiksi "paloherkkyys". Kokemuksen perusteella ei ole kauan, ennen kuin kaikki debuffien sisältämät pelisuunnittelut vaativat näitä.
  • 1 @StephaneHockenhull sanottu hyvin!

Koodi ei tunnu luovan loputonta silmukkaa.

Ainoa tapa, jolla silmukka olisi ääretön, olisi jos

debuf.ApplyToDamage(resolvedDamage); 

tai

DestroyMe(); 

piti lisätä uusia kohteita m_debufs astiaan.

Tämä näyttää epätodennäköiseltä. Ja jos näin olisi, ohjelma saattaa kaatua, koska säilö on vaihdettu iteroinnin aikana.

Ohjelma kaatuu todennäköisesti puhelun vuoksi DestroyMe(); mikä oletettavasti tuhoaa silmukan parhaillaan käynnissä olevan objektin.

Voimme ajatella sitä sarjakuvana, jossa 'paha kaveri' sahaa oksan saadakseen 'hyvän kaverin' putoamaan sen mukana, mutta tajuaa liian myöhään, että hän on leikkauksen väärällä puolella. Tai Midgaard Snake syö sen omaa häntää.


Haluan myös lisätä, että äärettömän silmukan yleisin oire on se, että se pysäyttää ohjelman tai ei reagoi siihen. Se kaataa ohjelman, jos se jakaa muistia toistuvasti tai tekee jotain, joka lopulta jaetaan nollalla, tai tykkäykset.


Aki Tanakan kommentin perusteella

Todennäköisesti hyödyllinen: uusi kuvakaappaus Umikosta sanomalla, että "Se kutsui samaa operaatiota uudestaan ​​ja uudestaan", mikä ei ehkä näy koodissa.

"Se kutsui samaa operaatiota uudestaan ​​ja uudestaan" Tämä on todennäköisempää.

Olettaen että DestroyMe(); ei ole suunniteltu kutsumaan useammin kuin kerran, se aiheuttaa todennäköisemmin kaatumisen.

Tapa korjata tämä ongelma olisi muuttaa if jotain tällaista:

 if (m_currentHealth <= 0.f) { m_currentHealth = 0.f; DestroyMe(); break; } 

Tämä sulkisi silmukan, kun DestructibleActor tuhoutuu, varmistaen, että 1) DestroyMe menetelmää kutsutaan vain kerran ja 2) älä käytä buffeja turhaan, kun objekti on jo kuollut.

2
  • 1 Katkaisu for-silmukasta, kun terveys <= 0 on ehdottomasti parempi korjaus kuin odottaa silmukan jälkeen terveyden tarkistamiseksi.
  • Luulen, että luultavasti break ulos silmukasta, ja sitten puhelu DestroyMe()vain turvallisuuden vuoksi

Koodissa on useita ongelmia:

  1. Jos debuffeja ei ole, vahinkoja ei aiheudu.
  2. DestroyMe() toiminnon nimi kuulostaa vaaralliselta. Riippuen siitä, miten se toteutetaan, se saattaa olla ongelma. Jos se on vain kutsu funktioon käärittyyn nykyisen objektin tuhoajaan, on ongelma, koska objekti tuhoutuisi sen keskellä suorittamalla koodia. Jos se on kutsu funktiolle, joka jonottaa nykyisen objektin poistotapahtuman, ei ole ongelmaa, koska objekti tuhoutuisi sen jälkeen, kun se on suorittanut suorituksensa ja tapahtumasilmukka käynnistyy.
  3. Todellinen kysymys, joka näyttää mainittavan animessa, "Se kutsui samaa operaatiota uudestaan ​​ja uudestaan" - se kutsuu DestroyMe() niin kauan kuin m_currentHealth <= 0.f ja jäljellä on vielä useita debuffeja, jotka saattavat johtaa DestroyMe() soitetaan useita kertoja uudestaan ​​ja uudestaan. Silmukan tulisi pysähtyä ensimmäisen jälkeen DestroyMe() kutsu, koska objektin poistaminen useammin kuin kerran johtaa muistivirheisiin, mikä todennäköisesti johtaa kaatumiseen pitkällä aikavälillä.

En ole oikeastaan ​​varma, miksi jokainen debuf vie terveyden sen sijaan, että terveys otettaisiin pois vain kerran, ja kaikkien debuffien vaikutukset alkuperäiseen vahinkoon, mutta oletan, että se on oikea pelilogiikka.

Oikea koodi olisi

// the calculation of damage when attacked void DestructibleActor::ReceiveDamage(float sourceDamage) { // apply debuffs auto resolvedDamage = sourceDamage; for (const auto& debuf:m_debufs) { resolvedDamage = debuf.ApplyToDamage(resolvedDamage); m_currentHealth -= resolvedDamage if (m_currentHealth <= 0.f) { m_currentHealth = 0.f; DestroyMe(); break; } } } 
3
  • Haluan huomauttaa, että koska olen kirjoittanut muistinjakolaitteita aiemmin, saman muistin poistamisen ei tarvitse olla ongelma. Se voi myös olla tarpeeton. Kaikki riippuu allokaattorin käyttäytymisestä. Oma toimi vain kuten matalan tason linkitetty luettelo, joten poistettujen tietojen "solmu" joko asetetaan vapaaksi useita kertoja tai palautetaan useita kertoja (mikä vastaisi vain tarpeettomia osoittimen uudelleenohjauksia). Hyvä saalis kuitenkin.
  • Tupla-vapaa on vika, ja se johtaa yleensä määrittelemättömään käyttäytymiseen ja kaatuu. Vaikka sinulla olisi mukautettu allokaattori, joka jotenkin estää saman muistiosoitteen uudelleenkäytön, kaksoisvapaa on haiseva koodi, koska sillä ei ole mitään järkeä ja staattiset koodianalysaattorit saavat sinut huutamaan.
  • Tietysti! En suunnitellut sitä tähän tarkoitukseen. Jotkut kielet tarvitsevat vain kohdistimen ominaisuuksien puutteen vuoksi. Ei ei ei. Totesin vain, että kaatumista ei voida taata. Tietyt malliluokitukset eivät aina kaadu.