add $killcount command
This commit is contained in:
@@ -506,6 +506,7 @@ Some commands only work on the game server and not on the proxy server. The chat
|
||||
* `$si` (game server only): Show basic information about the server.
|
||||
* `$ping`: Show round-trip ping time from the server to you. On the proxy server, show the ping time from you to the proxy and from the proxy to the server.
|
||||
* `$matcount` (game server only): Show how many of each type of material you've used.
|
||||
* `$killcount` (game server only): Show the kill count on your currently-equipped weapon. If you're in a game and not on BB, the value is only accurate at the time the item enters the game.
|
||||
* `$itemnotifs <mode>`: Enable item drop notification messages. If the game has private drops enabled, you will only see a notification if the dropped item is visible to you; you won't be notified of other players' drops. The modes are:
|
||||
* `off`: No notifications are shown.
|
||||
* `rare`: You are notified when a rare item drops.
|
||||
|
||||
@@ -724,6 +724,35 @@ static void server_command_show_material_counts(shared_ptr<Client> c, const std:
|
||||
}
|
||||
}
|
||||
|
||||
static void server_command_show_kill_count(shared_ptr<Client> c, const std::string&) {
|
||||
auto p = c->character();
|
||||
size_t item_index;
|
||||
try {
|
||||
item_index = p->inventory.find_equipped_item(EquipSlot::WEAPON);
|
||||
} catch (const out_of_range&) {
|
||||
send_text_message(c, "No weapon equipped");
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& item = p->inventory.items.at(item_index);
|
||||
if (!item.data.has_kill_count()) {
|
||||
send_text_message(c, "Weapon does not\nhave a kill count");
|
||||
return;
|
||||
}
|
||||
|
||||
// Kill counts are only accurate on the server side at all times on BB. On
|
||||
// other versions, we update the server's view of the client's inventory
|
||||
// during games, but we can't track kills because the client doesn't inform
|
||||
// the server whether it counted a kill for any individual enemy. So, on
|
||||
// non-BB versions, the kill count is accurate at all times in the lobby
|
||||
// (since kills can't occur there), or at the beginning of a game.
|
||||
if ((c->version() == Version::BB_V4) || !c->require_lobby()->is_game()) {
|
||||
send_text_message_printf(c, "%hu kills", item.data.get_kill_count());
|
||||
} else {
|
||||
send_text_message_printf(c, "%hu kills as of\ngame join", item.data.get_kill_count());
|
||||
}
|
||||
}
|
||||
|
||||
static void server_command_auction(shared_ptr<Client> c, const std::string&) {
|
||||
check_account_flag(c, Account::Flag::DEBUG);
|
||||
auto l = c->require_lobby();
|
||||
@@ -2536,6 +2565,7 @@ static const unordered_map<string, ChatCommandDefinition> chat_commands({
|
||||
{"$itemnotifs", {server_command_item_notifs, proxy_command_item_notifs}},
|
||||
{"$i", {server_command_item, proxy_command_item}},
|
||||
{"$kick", {server_command_kick, nullptr}},
|
||||
{"$killcount", {server_command_show_kill_count, nullptr}},
|
||||
{"$li", {server_command_lobby_info, proxy_command_lobby_info}},
|
||||
{"$ln", {server_command_lobby_type, proxy_command_lobby_type}},
|
||||
{"$loadchar", {server_command_loadchar, nullptr}},
|
||||
|
||||
@@ -480,7 +480,8 @@ ItemData ItemNameIndex::parse_item_description_phase(const std::string& descript
|
||||
ret.data1[2] = (primary_identifier >> 8) & 0xFF;
|
||||
|
||||
if (ret.data1[0] == 0x00) {
|
||||
// Weapons: add special, grind and percentages (or name, if S-rank)
|
||||
// Weapons: add special, grind and percentages (or name, if S-rank) and
|
||||
// kill count if unsealable
|
||||
ret.data1[4] = weapon_special | (is_wrapped ? 0x40 : 0x00) | (is_unidentified ? 0x80 : 0x00);
|
||||
|
||||
auto tokens = phosg::split(desc, ' ');
|
||||
@@ -516,13 +517,14 @@ ItemData ItemNameIndex::parse_item_description_phase(const std::string& descript
|
||||
if (p_tokens.size() > 5) {
|
||||
throw runtime_error("invalid bonuses token");
|
||||
}
|
||||
uint8_t max_bonuses = this->item_parameter_table->is_unsealable_item(ret) ? 2 : 3;
|
||||
uint8_t bonus_index = 0;
|
||||
for (size_t z = 0; z < p_tokens.size(); z++) {
|
||||
int8_t bonus_value = stol(p_tokens[z], nullptr, 10);
|
||||
if (bonus_value == 0) {
|
||||
continue;
|
||||
}
|
||||
if (bonus_index >= 3) {
|
||||
if (bonus_index >= max_bonuses) {
|
||||
throw runtime_error("weapon has too many bonuses");
|
||||
}
|
||||
ret.data1[6 + (2 * bonus_index)] = z + 1;
|
||||
@@ -532,6 +534,10 @@ ItemData ItemNameIndex::parse_item_description_phase(const std::string& descript
|
||||
}
|
||||
}
|
||||
|
||||
if (this->item_parameter_table->is_unsealable_item(ret)) {
|
||||
ret.set_kill_count(0);
|
||||
}
|
||||
|
||||
} else if (ret.data1[0] == 0x01) {
|
||||
if (ret.data1[1] == 0x03) { // Unit
|
||||
static const unordered_map<string, uint16_t> modifiers({
|
||||
|
||||
Reference in New Issue
Block a user