Przed startem obecnego sezonu LiGNA WTCC, poszukiwalem jak odczytywac upgradecode z logow w rFactor. Bylo to niezbedne do kontroli balastu z upgrade'ow (dlaczego nie uzylismy komendy setmass to zupelnie inna bajka). Niestety nigdzie w internecie nie udalo mi sie znalesc jakichkolwiek wskazowek czym on jest. Jedynie znalazlem wzmianke, ze faktycznie on dziala. Tam gdzie sie dogrzebalem radzono, zeby recznie sprawdzic i spisac kod dla wszystkich kombinacji upgrade'ow i na tej podstawie pozniej odczytywac. Oczywiscie jest lepszy sposob, do ktorego udalo mi sie dojsc metoda prob i bledow.
Zamieszczam to tutaj, poniewaz o ile mi wiadomo, jest to
jedyne miejsce gdzie jest to opisane, wiec moze warto temat przypiac (chociaz w sumie watpie zeby ktokolwiek tego uzyl).
Wprowadzenie. W LiGNA WTCC wszystkie auta (poza BMW...) maja nastepujace upgrade'y:
FFB : (normal, medium, hard)
Balast : (no balast, -20, -15, -10, -5, 5, ..., 80kg)
Interior windscreen: (normal, clear)
Kolejnosc upgradeow ma istotne znaczenie. Link do pliku z upgrade'ami:
http://bandit.zapto.org/rFactor/LiGNA_W ... grades.iniBMW ma jeszcze jeden upgrade, ale tylko z jednym poziomem, wiec nie powinien miec wplywu na obliczanie kodu balastu, tzn dla kazdego auta upgradecode powinien sie identycznie liczyc.
Poziom upgrade'u jest numerowany od 0. Wiec np Poziom -10kg balastu, ma numer 3. +80kg ma numer 20. Clear windscreen ma numer 1.
w pliku *.xml
- Kod: Zaznacz cały
<Driver>
<Name>B4ndIt</Name>
<Connected>1</Connected>
<VehFile>03_ALFA_156.VEH</VehFile>
[u][b]<UpgradeCode>91000000 00000000</UpgradeCode>[/b][/u]
<VehName>Alfa Romeo Team 2 #66 - Unikalny Nick</VehName>
<CarType>Alfa Romeo 156</CarType>
<CarClass>WTCC</CarClass>
<CarNumber>66</CarNumber>
<TeamName>Cuore Sportivo</TeamName>
<isPlayer>1</isPlayer>
<Position>1</Position>
<ClassPosition>1</ClassPosition>
<Points>0</Points>
<ClassPoints>0</ClassPoints>
<LapRankIncludingDiscos>1</LapRankIncludingDiscos>
<Laps>0</Laps>
<Pitstops>0</Pitstops>
<FinishStatus>None</FinishStatus>
</Driver>
Dla tego konkretnego pliku z upgrade'ami, upgradecode jest obliczany w taki sposob:
ffb_poziom + balast_poziom * 4 + wind_poziom * 128
gdzie
- ffb_poziom, ktory to jest w kolejnosci upgrade ffb (domyslny = 0, medium = 1, hard = 2)
- balast_poziom, ktory to jest w kolejnosci upgrade balastu (domyslny = 0, -20kg = 1, -15kg = 2, ..., +80kg = 22)
- wind_poziom, ktory to jest w kolejnosci upgrade balastu szyby przedniej (domyslny = 0, clear = 1)
Co tu sie faktycznie dzieje? napisał(a):Dlaczego tam sie mnozy razy 4 i razy 128? Po to zeby bity kodujace kolejne upgrade'y na siebie nie nachodzily
Pierwsze 2 bity sa zarezerwowane na kod ffb. Nastepne 5 bitow sluzy do zakodowania balastu. Ostatni bit sluzy do zakodowania poziomu interior windscreen. Dlaczego akurat tyle bitow? 2 bity to minimalna ilosc zeby zakodowac 3 rozne upgrade'y ffb. 5 bitow, to minimalna ilosc zeby zakodowac 21 upgrade'ow balastu. 1 bit do zakodowania 2 upgrade'ow szyby.
przyklady korzystania z wzoru:
UpgradeCode, to kod szestnastkowy, jednoznacznie identyfikujacy uzyte upgrade'y. Przykladowe wartosci sprawdzone przeze mnie w praktyce na serwerze.
- Kod: Zaznacz cały
ffb 0, Honda 0kg, wind 0
<UpgradeCode>00000000 00000000</UpgradeCode>
ffb 0, Honda 20kg, wind 0
<UpgradeCode>04000000 00000000</UpgradeCode>
0 + 1 * 4 + 0 * 128 = 4
ffb 0, Honda -15kg, wind 0
<UpgradeCode>08000000 00000000</UpgradeCode>
0 + 2 * 4 + 0 * 128 = 8
ffb 0, Honda -5kg, wind 0
<UpgradeCode>10000000 00000000</UpgradeCode>
0 + 4 * 4 + 0 * 128 = 16 = 10 (szestnastkowo)
ffb 1, Honda -5kg, wind 0
<UpgradeCode>11000000 00000000</UpgradeCode>
1 + 4 * 4 + 0 * 128 = 17 = 11 (szestnastkowo)
ffb 1, Honda -5kg, wind 1
<UpgradeCode>91000000 00000000</UpgradeCode>
1 + 4 * 4 + 1 * 128 = 145 = 91 (szestnastkowo)
ffb 1, Alfa -5kg, wind 1
<UpgradeCode>91000000 00000000</UpgradeCode>
[b]Jak widac taki sam kod jak w Hondzie[/b]
ffb 2, Alfa 80kg, wind 1
<UpgradeCode>d2000000 00000000</UpgradeCode>
1 + 20 * 4 + 1 * 128 = 210 = d2 (szestnastkowo)
- Kod: Zaznacz cały
Numery balastu
numer wartosc
0 0kg
1 -20kg
2 -15kg
3 -10kg
4 -5kg
5 5kg
6 10kg
7 15kg
8 20kg
9 25kg
10 30kg
11 35kg
12 40kg
13 45kg
14 50kg
15 55kg
16 60kg
17 65kg
18 70kg
19 75kg
20 80kg
Fragmenty kodu w python'ie do dekodowania upgradecode, dla dowolnego pliku z upgrade'ami:
- Kod: Zaznacz cały
from lxml import etree
from math import pow, ceil, log
import re
(...)
code = driver.xpath("UpgradeCode/text()")[0]
code = code.replace(" ", "")
code = int(code, 16)
last_bit = 64
entry = list()
for type in reversed(self.upgrades):
size = ceil(log( len(type), 2))
number = code % int(pow(2, last_bit))
number /= int(pow(2, last_bit - size))
last_bit = last_bit - size
entry.append(type[int(number)])
- Kod: Zaznacz cały
def parseupgrades(upgrades_file):
upgrades = []
content = upgrades_file.read()
content = re.sub("//[^\n]*", "", content)
types = re.split("UpgradeType", content)
for type in types:
levels = re.findall("UpgradeLevel=\"([^\n]*)\"", type)
if len(levels) > 0:
upgrades.append( levels )
return upgrades
upgrades_file to plik z upgrade'ami (content to string). Wynik "parseupgrades" jest potem przekazywany do zmiennej "self.upgrades". Jesli ktos nie ma chocby bladego pojecia co powyzszy kod robi, to prosze mi nie zawracac o to glowy, bo nie mam na to czasu. Wszystkie powyzsze informacje zamieszczam "as it is"