Śpieszę z wyjaśnieniami.
Operatory bitowe są używane zwykle nie z normalnie wklepanymi liczbami dziesiętnymi, ale maskami bitowymi. To także liczby, ale pisane nie ze względu na ich wartość liczbową, ale układ bitów. Najprostsze mają same zera i jedną jedynkę na którejś pozycji. Nie da się bezpośrednio wklepywać zer i jedynek, więc używa się dla osiągnięcia czegoś takiego operatorów przesunięcia bitowego. Biorą one daną liczbę i przesuwają ją w daną stronę o daną ilość bitów, po brakującej stronie dodając zera. Zer z lewej możemy w wyobraźni dopisywać sobie ile chcemy, bo są bez znaczenia. Dajemy ich tyle, żeby długość liczb którymi operujemy się pokrywała.
Przykładowo (w komentarzu zapis bitowy):
const int jeden = 1 ; // 0001
const int tezjeden = 1 << 0; // 0001 //przesunęliśmy o 0 bitów, czyli dostaliśmy 1 * 2^0 = 1
const int dwa = 1 << 1; // 0010 //przesunęliśmy o 1 bit, czyli dostaliśmy 1 * 2^1 = 2
const int cztery = 1 << 2; // 0100 //przesunęliśmy o 2 bity, czyli dostaliśmy 1 * 2^2 = 4
Teraz zobaczmy jak działa operator | (OR) użyty na takich maskach:
const int szesc = dwa | cztery; // 0010 | 0100 = 0110 //w wyniku jedynki są tam, gdzie była jedynka w którymkolwiek z operandów
Jak widać, możemy traktować każdy bit jako "pojemnik" i za pomocą różnych funkcji matematycznych czytać go lub zapisywać. Tak jakby był całą tablicą wartości tak/nie.
Taki mechanizm nazywany jest polem bitowym. Jest to używane między innymi z flagsami itemów. Dlatego item może mieć zapisane za pomocą | kilka różnych flag w jednej liczbie, a silnik jest w stanie rozczytać które to były flagi. Dlatego też te flagi są definiowane w taki sposób jak pokazałem powyżej i w poprzednim poście:
CONST INT ITEM_SWD = 1 << 14;
CONST INT ITEM_AXE = 1 << 15;
CONST INT ITEM_BOW = 1 << 19;
Z gildiami jest inaczej. Mają zwykłe kolejne wartości:
CONST INT GIL_EBR = 1;
CONST INT GIL_GRD = 2;
CONST INT GIL_STT = 3;
Kiedy wykonasz na nich operację | (OR), to w odróżnieniu od poprzedniego przykładu, z tego co wyjdzie nie będzie się dało stwierdzić co "weszło":
CONST INT ownerguild = GIL_EBR | GIL_GRD; // 0001 | 0010 = 3
Silnik nie jest w stanie w żaden sposób stwierdzić czy te trzy które wyszło to rezultat dodania do siebie gildii ebr i grd, czy po prostu wklepana gildia stt.
Mogłoby to działać, gdyby gildie także miały przypisane wartości na zasadzie masek bitowych:
CONST INT GIL_EBR = 1 << 0; //0001
CONST INT GIL_GRD = 1 << 1; //0010
CONST INT GIL_STT = 1 << 2; //0100
CONST INT ownerguild = GIL_EBR | GIL_GRD; // 0001 | 0010 = 0011
Tym razem jest to co innego niż gil_stt, silnik jest w stanie bardzo łatwo znowu rozbić to na pojedyncze bity i dowiedzieć się jakie były wartości składowe - tak jak z flagsami itemów. Ale z gildiami nie jest to zaprogramowane, więc zwyczajnie nie możesz tak robić.