summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/admin/ladmin.cpp14
-rw-r--r--src/ast/item_test.cpp2
-rw-r--r--src/char/char.cpp76
-rw-r--r--src/login/login.cpp57
-rw-r--r--src/map/atcommand.cpp34
-rw-r--r--src/map/chrif.cpp5
-rw-r--r--src/map/clif.cpp6
-rw-r--r--src/map/pc.cpp35
-rw-r--r--src/mmo/enums.hpp9
-rwxr-xr-xtools/config.py6
-rwxr-xr-xtools/protocol.py7
11 files changed, 109 insertions, 142 deletions
diff --git a/src/admin/ladmin.cpp b/src/admin/ladmin.cpp
index e0d6b06..ac9be1d 100644
--- a/src/admin/ladmin.cpp
+++ b/src/admin/ladmin.cpp
@@ -205,7 +205,7 @@ namespace admin
//
// sex <account_name> <sex>
// Modify the sex of an account.
-// <example> sex testname Male
+// <example> sex testname M
//
// state <account_name> <new_state> <error_message_#7>
// Change the state of an account.
@@ -490,7 +490,7 @@ void display_help(ZString param)
{
PRINTF("sex <account_name> <sex>\n"_fmt);
PRINTF(" Modify the sex of an account.\n"_fmt);
- PRINTF(" <example> sex testname Male\n"_fmt);
+ PRINTF(" <example> sex testname M\n"_fmt);
}
else if (command == "state"_s)
{
@@ -627,7 +627,7 @@ void addaccount(ZString param, int emailflag)
if (!name.is_print())
return;
- if (!"MF"_s.contains(sex))
+ if (!"MFN"_s.contains(sex))
{
PRINTF("Illegal gender [%c]. Please input M or F.\n"_fmt, sex);
LADMIN_LOG("Illegal gender [%c]. Please input M or F.\n"_fmt, sex);
@@ -1291,7 +1291,7 @@ void changesex(ZString param)
if (!qsplit(param, &name, &sex_))
{
PRINTF("Please input an account name and a sex.\n"_fmt);
- PRINTF("<example> sex testname Male\n"_fmt);
+ PRINTF("<example> sex testname M\n"_fmt);
LADMIN_LOG("Incomplete parameters to change the sex of an account ('sex' command).\n"_fmt);
return;
}
@@ -1303,7 +1303,7 @@ void changesex(ZString param)
return;
}
- if (!"MF"_s.contains(sex))
+ if (!"MFN"_s.contains(sex))
{
PRINTF("Illegal gender [%c]. Please input M or F.\n"_fmt, sex);
LADMIN_LOG("Illegal gender [%c]. Please input M or F.\n"_fmt, sex);
@@ -1750,6 +1750,8 @@ void parse_fromlogin(Session *s)
PRINTF("%-5s "_fmt, "Femal"_s);
else if (info.sex == SEX::MALE)
PRINTF("%-5s "_fmt, "Male"_s);
+ else if (info.sex == SEX::NEUTRAL)
+ PRINTF("%-5s "_fmt, "None"_s);
else
PRINTF("%-5s "_fmt, "Servr"_s);
PRINTF("%6d "_fmt, info.login_count);
@@ -2347,6 +2349,8 @@ void parse_fromlogin(Session *s)
PRINTF(" Sex: Female\n"_fmt);
else if (sex == SEX::MALE)
PRINTF(" Sex: Male\n"_fmt);
+ else if (sex == SEX::NEUTRAL)
+ PRINTF(" Sex: None\n"_fmt);
else // doesn't happen anymore
PRINTF(" Sex: Server\n"_fmt);
PRINTF(" E-mail: %s\n"_fmt, email);
diff --git a/src/ast/item_test.cpp b/src/ast/item_test.cpp
index 6e2cee7..7bb7193 100644
--- a/src/ast/item_test.cpp
+++ b/src/ast/item_test.cpp
@@ -127,7 +127,7 @@ namespace item
EXPECT_SPAN(p->slot_unused.span, 1,31, 1,32);
EXPECT_EQ(p->slot_unused.data, "xx"_s);
EXPECT_SPAN(p->gender.span, 1,34, 1,34);
- EXPECT_EQ(p->gender.data, SEX::NEUTRAL);
+ EXPECT_EQ(p->gender.data, SEX::UNSPECIFIED);
EXPECT_SPAN(p->loc.span, 1,36, 1,37);
EXPECT_EQ(p->loc.data, EPOS::MISC1);
EXPECT_SPAN(p->wlv.span, 1,39, 1,40);
diff --git a/src/char/char.cpp b/src/char/char.cpp
index 0958c5e..1dc0e90 100644
--- a/src/char/char.cpp
+++ b/src/char/char.cpp
@@ -235,6 +235,16 @@ AString mmo_char_tostr(struct CharPair *cp)
{
p->last_point = char_conf.start_point;
}
+ if (p->sex == SEX::UNSPECIFIED)
+ {
+ for (AuthFifoEntry& afi : auth_fifo)
+ {
+ if (afi.account_id == k->account_id)
+ {
+ p->sex = afi.sex;
+ }
+ }
+ }
MString str_p;
str_p += STRPRINTF(
@@ -251,7 +261,8 @@ AString mmo_char_tostr(struct CharPair *cp)
"%d,%d,%d\t"
"%d,%d,%d,%d,%d\t"
"%s,%d,%d\t"
- "%s,%d,%d,%d\t"_fmt,
+ "%s,%d,%d,%d\t"
+ "%c\t"_fmt,
k->char_id,
k->account_id, k->char_num,
k->name,
@@ -265,10 +276,8 @@ AString mmo_char_tostr(struct CharPair *cp)
p->hair, p->hair_color, p->clothes_color,
p->weapon, p->shield, p->head_top, p->head_mid, p->head_bottom,
p->last_point.map_, p->last_point.x, p->last_point.y,
- p->save_point.map_, p->save_point.x, p->save_point.y, p->partner_id);
-
- // memos were here (no longer supported)
- str_p += '\t';
+ p->save_point.map_, p->save_point.x, p->save_point.y, p->partner_id,
+ sex_to_char(p->sex));
for (IOff0 i : IOff0::iter())
{
@@ -352,6 +361,7 @@ bool impl_extract(XString str, CharPair *cp)
CharData *p = cp->data.get();
uint32_t unused_guild_id, unused_pet_id;
+ VString<1> sex;
XString unused_memos;
std::vector<Item> inventory;
XString unused_cart;
@@ -377,13 +387,17 @@ bool impl_extract(XString str, CharPair *cp)
// of this, instead of adding a new \t
// or putting it elsewhere, like by pet/guild
record<','>(&p->save_point.map_, &p->save_point.x, &p->save_point.y, &p->partner_id),
- &unused_memos,
+ &sex,
vrec<' '>(&inventory),
&unused_cart,
vrec<' '>(&skills),
vrec<' '>(&vars))))
return false;
+ if (sex.size() != 1)
+ p->sex = SEX::UNSPECIFIED;
+ else
+ p->sex = sex_from_char(sex.front());
// leftover corruption from Platinum
if (hair_style == "-1"_s)
{
@@ -706,6 +720,7 @@ CharPair *make_new_char(Session *s, CharName name, const Stats6& stats, uint8_t
ck.char_num = slot;
ck.name = name;
cd.species = Species();
+ cd.sex = SEX::NEUTRAL;
cd.base_level = 1;
cd.job_level = 1;
cd.base_exp = 0;
@@ -978,7 +993,10 @@ int mmo_char_send006b(Session *s, struct char_session_data *sd)
sel.stats.dex = saturate<uint8_t>(p->attrs[ATTR::DEX]);
sel.stats.luk = saturate<uint8_t>(p->attrs[ATTR::LUK]);
sel.char_num = k->char_num;
- sel.unused = 0;
+ if (p->sex == SEX::UNSPECIFIED)
+ sel.sex = sd->sex;
+ else
+ sel.sex = p->sex;
repeat_6b.push_back(info);
}
@@ -1257,29 +1275,6 @@ void parse_tologin(Session *ls)
SEX sex = fixed.sex;
if (acc)
{
- for (CharPair& cp : char_keys)
- {
- CharKey& ck = cp.key;
- CharData& cd = *cp.data;
- if (ck.account_id == acc)
- {
- cd.sex = sex;
-// auth_fifo[i].sex = sex;
- // to avoid any problem with equipment and invalid sex, equipment is unequiped.
- for (IOff0 j : IOff0::iter())
- {
- if (cd.inventory[j].nameid
- && bool(cd.inventory[j].equip))
- cd.inventory[j].equip = EPOS::ZERO;
- }
- cd.weapon = ItemLook::NONE;
- cd.shield = ItemNameId();
- cd.head_top = ItemNameId();
- cd.head_mid = ItemNameId();
- cd.head_bottom = ItemNameId();
- }
- }
- // disconnect player if online on char-server
disconnect_player(acc);
}
Packet_Fixed<0x2b0d> fixed_0d;
@@ -1694,7 +1689,6 @@ void parse_frommap(Session *ms)
Packet_Payload<0x2afd> payload_fd; // not file descriptor
payload_fd.account_id = account_id;
payload_fd.login_id2 = afi.login_id2;
- cd->sex = afi.sex;
payload_fd.packet_client_version = afi.packet_client_version;
FPRINTF(stderr,
"From queue index %zd: recalling packet version %d\n"_fmt,
@@ -1983,24 +1977,6 @@ void parse_frommap(Session *ms)
fixed_0f.error = 2;
break;
}
- case 5: // changesex
- {
- if (!acc
- || isGM(acc).overwhelms(isGM(ck->account_id)))
- {
- if (login_session)
- { // don't send request if no login-server
- Packet_Fixed<0x2727> fixed_27;
- fixed_27.account_id = ck->account_id;
- send_fpacket<0x2727, 6>(login_session, fixed_27);
- }
- else
- fixed_0f.error = 3;
- }
- else
- fixed_0f.error = 2;
- break;
- }
}
}
else
@@ -2437,7 +2413,7 @@ void parse_char(Session *s)
fixed_6d.char_select.stats.dex = saturate<uint8_t>(cd->attrs[ATTR::DEX]);
fixed_6d.char_select.stats.luk = saturate<uint8_t>(cd->attrs[ATTR::LUK]);
fixed_6d.char_select.char_num = ck->char_num;
- fixed_6d.char_select.unused2 = 0;
+ fixed_6d.char_select.sex = cd->sex;
send_fpacket<0x006d, 108>(s, fixed_6d);
break;
diff --git a/src/login/login.cpp b/src/login/login.cpp
index 9310ad3..c071429 100644
--- a/src/login/login.cpp
+++ b/src/login/login.cpp
@@ -441,8 +441,6 @@ bool impl_extract(XString line, AuthData *ad)
if (sex.size() != 1)
return false;
ad->sex = sex_from_char(sex.front());
- if (ad->sex == SEX::NEUTRAL)
- return false;
if (!e_mail_check(ad->email))
ad->email = DEFAULT_EMAIL;
@@ -881,7 +879,6 @@ void parse_fromchar(Session *s)
if (auth_fifo[i].account_id == acc &&
auth_fifo[i].login_id1 == fixed.login_id1 &&
auth_fifo[i].login_id2 == fixed.login_id2 && // relate to the versions higher than 18
- auth_fifo[i].sex == fixed.sex &&
auth_fifo[i].ip == fixed.ip
&& !auth_fifo[i].delflag)
{
@@ -1178,56 +1175,6 @@ void parse_fromchar(Session *s)
break;
}
- case 0x2727: // Change of sex (sex is reversed)
- {
- Packet_Fixed<0x2727> fixed;
- rv = recv_fpacket<0x2727, 6>(s, fixed);
- if (rv != RecvResult::Complete)
- break;
-
- {
- AccountId acc = fixed.account_id;
- for (AuthData& ad : auth_data)
- {
- if (ad.account_id == acc)
- {
- {
- SEX sex;
- if (ad.sex == SEX::FEMALE)
- sex = SEX::MALE;
- else
- sex = SEX::FEMALE;
- LOGIN_LOG("Char-server '%s': Sex change (account: %d, new sex %c, ip: %s).\n"_fmt,
- server[id].name, acc,
- sex_to_char(sex),
- ip);
- for (int j = 0; j < AUTH_FIFO_SIZE; j++)
- {
- if (auth_fifo[j].account_id == acc)
- auth_fifo[j].login_id1++; // to avoid reconnection error when come back from map-server (char-server will ask again the authentification)
- }
- ad.sex = sex;
-
- Packet_Fixed<0x2723> fixed_23;
- fixed_23.account_id = acc;
- fixed_23.sex = sex;
-
- for (Session *ss : iter_char_sessions())
- {
- send_fpacket<0x2723, 7>(ss, fixed_23);
- }
- }
- goto x2727_out;
- }
- }
- LOGIN_LOG("Char-server '%s': Error of sex change (account: %d not found, sex would be reversed, ip: %s).\n"_fmt,
- server[id].name, acc, ip);
- x2727_out:
- ;
- }
- break;
- }
-
case 0x2728: // We receive account_reg2 from a char-server, and we send them to other char-servers.
{
Packet_Head<0x2728> head;
@@ -1504,7 +1451,7 @@ void parse_admin(Session *s)
LOGIN_LOG("'ladmin': Attempt to create an invalid account (account or pass is too short, ip: %s)\n"_fmt,
ip);
}
- else if (ma.sex != SEX::FEMALE && ma.sex != SEX::MALE)
+ else if (ma.sex != SEX::FEMALE && ma.sex != SEX::MALE && ma.sex != SEX::NEUTRAL)
{
LOGIN_LOG("'ladmin': Attempt to create an invalid account (account: %s, invalid sex, ip: %s)\n"_fmt,
ma.userid, ip);
@@ -1765,7 +1712,7 @@ void parse_admin(Session *s)
{
SEX sex = fixed.sex;
- if (sex != SEX::FEMALE && sex != SEX::MALE)
+ if (sex != SEX::FEMALE && sex != SEX::MALE && sex != SEX::NEUTRAL)
{
LOGIN_LOG("'ladmin': Attempt to give an invalid sex (account: %s, received sex: %c, ip: %s)\n"_fmt,
account_name, sex_to_char(sex), ip);
diff --git a/src/map/atcommand.cpp b/src/map/atcommand.cpp
index 123a723..f50cddf 100644
--- a/src/map/atcommand.cpp
+++ b/src/map/atcommand.cpp
@@ -2348,12 +2348,36 @@ ATCE atcommand_char_change_sex(Session *s, dumb_ptr<map_session_data> sd,
ZString message)
{
CharName character;
+ VString<1> gender;
+ int operation;
- if (!asplit(message, &character))
+ if (!extract(message, record<' ', 1>(&character, &gender)))
+ {
+ clif_displaymessage(s,
+ "Please, enter a char name (usage: @charchangesex <char name> [Gender])."_s);
return ATCE::USAGE;
-
+ }
+ else
{
- chrif_char_ask_name(sd->status_key.account_id, character, 5, HumanTimeDiff());
+ if (sex_from_char(gender.front()) == SEX::FEMALE)
+ {
+ operation = 5;
+ }
+ else if (sex_from_char(gender.front()) == SEX::MALE)
+ {
+ operation = 6;
+ }
+ else if (sex_from_char(gender.front()) == SEX::NEUTRAL)
+ {
+ operation = 7;
+ }
+ else
+ {
+ clif_displaymessage(s,
+ "Please, enter a char name (usage: @charchangesex <char name> [Gender])."_s);
+ return ATCE::USAGE;
+ }
+ chrif_char_ask_name(sd->status_key.account_id, character, operation, HumanTimeDiff());
// type: 5 - changesex
clif_displaymessage(s, "Character name sends to char-server to ask it."_s);
}
@@ -5215,9 +5239,9 @@ Map<XString, AtCommandInfo> atcommand_info =
{"allstats"_s, {"[value]"_s,
60, atcommand_all_stats,
"Adjust all stats by value (or maximum)"_s}},
- {"charchangesex"_s, {"<charname>"_s,
+ {"charchangesex"_s, {"<charname> <sex>"_s,
60, atcommand_char_change_sex,
- "Flip a characters sex and disconnect them"_s}},
+ "Change a characters sex and disconnect them"_s}},
{"block"_s, {"<charname>"_s,
60, atcommand_char_block,
"Permanently block a player's account from the server"_s}},
diff --git a/src/map/chrif.cpp b/src/map/chrif.cpp
index ce5669e..7421344 100644
--- a/src/map/chrif.cpp
+++ b/src/map/chrif.cpp
@@ -554,10 +554,7 @@ void chrif_changedsex(Session *, const Packet_Fixed<0x2b0d>& fixed)
{
if (sd != nullptr && sd->status.sex != sex)
{
- if (sd->status.sex == SEX::MALE)
- sd->sex = sd->status.sex = SEX::FEMALE;
- else if (sd->status.sex == SEX::FEMALE)
- sd->sex = sd->status.sex = SEX::MALE;
+ sd->sex = sd->status.sex = sex;
// to avoid any problem with equipment and invalid sex, equipment is unequiped.
for (IOff0 i : IOff0::iter())
{
diff --git a/src/map/clif.cpp b/src/map/clif.cpp
index 64e9939..9743e49 100644
--- a/src/map/clif.cpp
+++ b/src/map/clif.cpp
@@ -659,7 +659,7 @@ void clif_set0078_main_1d8(dumb_ptr<map_session_data> sd, Buffer& buf)
fixed_1d8.manner = sd->status.manner;
fixed_1d8.opt3 = sd->opt3;
fixed_1d8.karma = sd->status.karma;
- fixed_1d8.sex = sd->sex;
+ fixed_1d8.sex = sd->status.sex;
fixed_1d8.pos.x = sd->bl_x;
fixed_1d8.pos.y = sd->bl_y;
fixed_1d8.pos.dir = sd->dir;
@@ -713,7 +713,7 @@ void clif_set0078_alt_1d9(dumb_ptr<map_session_data> sd, Buffer& buf)
fixed_1d8.manner = sd->status.manner;
fixed_1d8.opt3 = sd->opt3;
fixed_1d8.karma = sd->status.karma;
- fixed_1d8.sex = sd->sex;
+ fixed_1d8.sex = sd->status.sex;
fixed_1d8.pos.x = sd->bl_x;
fixed_1d8.pos.y = sd->bl_y;
fixed_1d8.pos.dir = sd->dir;
@@ -766,7 +766,7 @@ void clif_set007b(dumb_ptr<map_session_data> sd, Buffer& buf)
fixed_1da.manner = sd->status.manner;
fixed_1da.opt3 = sd->opt3;
fixed_1da.karma = sd->status.karma;
- fixed_1da.sex = sd->sex;
+ fixed_1da.sex = sd->status.sex;
fixed_1da.pos2.x0 = sd->bl_x;
fixed_1da.pos2.y0 = sd->bl_y;
fixed_1da.pos2.x1 = sd->to_x;
diff --git a/src/map/pc.cpp b/src/map/pc.cpp
index 254ecb5..cb115c3 100644
--- a/src/map/pc.cpp
+++ b/src/map/pc.cpp
@@ -627,7 +627,7 @@ int pc_isequip(dumb_ptr<map_session_data> sd, IOff0 n)
return 1;
P<struct item_data> item = TRY_UNWRAP(sd->inventory_data[n], return 0);
- if (item->sex != SEX::NEUTRAL && sd->status.sex != item->sex)
+ if (item->sex != SEX::UNSPECIFIED && sd->status.sex != item->sex)
return 0;
if (item->elv > 0 && sd->status.base_level < item->elv)
return 0;
@@ -657,12 +657,6 @@ int pc_authok(AccountId id, int login_id2,
sd->status_key = *st_key;
sd->status = *st_data;
- if (sd->status.sex != sd->sex)
- {
- clif_authfail_fd(sd->sess, 0);
- return 1;
- }
-
MAP_LOG_STATS(sd, "LOGIN"_fmt);
MAP_LOG_XP(sd, "LOGIN"_fmt);
MAP_LOG_MAGIC(sd, "LOGIN"_fmt);
@@ -2129,7 +2123,7 @@ int pc_isUseitem(dumb_ptr<map_session_data> sd, IOff0 n)
if (itemdb_type(nameid) != ItemType::USE)
return 0;
- if (item->sex != SEX::NEUTRAL && sd->status.sex != item->sex)
+ if (item->sex != SEX::UNSPECIFIED && sd->status.sex != item->sex)
return 0;
if (item->elv > 0 && sd->status.base_level < item->elv)
return 0;
@@ -3361,7 +3355,7 @@ int pc_readparam(dumb_ptr<map_session_data> sd, SP type)
val = unwrap<Species>(sd->status.species);
break;
case SP::SEX:
- val = static_cast<uint8_t>(sd->sex);
+ val = static_cast<uint8_t>(sd->status.sex);
break;
case SP::WEIGHT:
val = sd->weight;
@@ -3493,7 +3487,28 @@ int pc_setparam(dumb_ptr<map_session_data> sd, SP type, int val)
}
break;
case SP::SEX:
- chrif_char_ask_name(AccountId(), sd->status_key.name, 5, HumanTimeDiff());
+ switch (val)
+ {
+ case 0:
+ sd->sex = sd->status.sex = SEX::FEMALE;
+ break;
+ case 1:
+ sd->sex = sd->status.sex = SEX::MALE;
+ break;
+ default:
+ sd->sex = sd->status.sex = SEX::NEUTRAL;
+ break;
+ }
+ for (IOff0 j : IOff0::iter())
+ {
+ if (sd->status.inventory[j].nameid
+ && bool(sd->status.inventory[j].equip)
+ && !pc_isequip(sd, j))
+ pc_unequipitem(sd, j, CalcStatus::LATER);
+ }
+ pc_calcstatus(sd, 0);
+ chrif_save(sd);
+ clif_fixpcpos(sd);
break;
case SP::WEIGHT:
sd->weight = val;
diff --git a/src/mmo/enums.hpp b/src/mmo/enums.hpp
index caecc13..9a8f8ea 100644
--- a/src/mmo/enums.hpp
+++ b/src/mmo/enums.hpp
@@ -113,7 +113,8 @@ enum class SEX : uint8_t
MALE = 1,
// For items. This is also used as error, sometime.
// TODO switch to Option<SEX> where appropriate.
- NEUTRAL = 2,
+ UNSPECIFIED = 2,
+ NEUTRAL = 3,
};
inline
char sex_to_char(SEX sex)
@@ -122,7 +123,8 @@ char sex_to_char(SEX sex)
{
case SEX::FEMALE: return 'F';
case SEX::MALE: return 'M';
- default: return '\0';
+ case SEX::NEUTRAL: return 'N';
+ default: return 'S';
}
}
inline
@@ -132,7 +134,8 @@ SEX sex_from_char(char c)
{
case 'F': return SEX::FEMALE;
case 'M': return SEX::MALE;
- default: return SEX::NEUTRAL;
+ case 'N': return SEX::NEUTRAL;
+ default: return SEX::UNSPECIFIED;
}
}
diff --git a/tools/config.py b/tools/config.py
index cedaa3a..0892973 100755
--- a/tools/config.py
+++ b/tools/config.py
@@ -555,9 +555,9 @@ def build_config():
char_conf.opt('max_hair_style', u16, '20', min=1)
char_conf.opt('max_hair_color', u16, '11', min=1)
char_conf.opt('min_stat_value', u16, '1')
- char_conf.opt('max_stat_value', u16, '9', min=2)
- char_conf.opt('total_stat_sum', u16, '30', min=7)
- char_conf.opt('min_name_length', u16, '4', min=1)
+ char_conf.opt('max_stat_value', u16, '9', min=1)
+ char_conf.opt('total_stat_sum', u16, '30', min=6)
+ char_conf.opt('min_name_length', u16, '4', min=4)
char_conf.opt('char_slots', u16, '9', min=1)
char_conf.opt('anti_freeze_enable', bool, 'false')
char_conf.opt('anti_freeze_interval', seconds, '6_s', min='5_s')
diff --git a/tools/protocol.py b/tools/protocol.py
index f7be6e5..8c3a677 100755
--- a/tools/protocol.py
+++ b/tools/protocol.py
@@ -1638,7 +1638,7 @@ def build_context():
at(98, stats6, 'stats'),
at(104, u8, 'char num'),
- at(105, u8, 'unused2'),
+ at(105, sex, 'sex'),
],
size=106,
)
@@ -4971,8 +4971,9 @@ def build_context():
fixed=[
at(0, u16, 'packet id'),
at(2, account_id, 'account id'),
+ at(6, sex, 'sex'),
],
- fixed_size=6,
+ fixed_size=7,
pre=[0x2b0e],
post=[0x2723],
desc='''
@@ -5406,7 +5407,7 @@ def build_context():
at(6, sex, 'sex'),
],
fixed_size=7,
- pre=[0x2723],
+ pre=[NOTHING],
post=[0x00ac, 0x01d7, 0x2b01, 0x3011],
xpost=[SCRIPT, 0x0080, 0x0081, 0x0088, 0x0091, 0x00a0, 0x00b0, 0x00b1, 0x00be, 0x00c0, 0x00e9, 0x00ee, 0x00fd, 0x0106, 0x010f, 0x0119, 0x013a, 0x0141, 0x0196, 0x01b1, 0x01d8, 0x01da, 0x2b05, 0x3022],
desc='''