make $item more powerful

This commit is contained in:
Martin Michelsen
2023-01-19 19:12:12 -08:00
parent 7a5e759d9a
commit 9b136d9444
12 changed files with 68 additions and 66 deletions
+22 -13
View File
@@ -5,6 +5,7 @@
#include <vector>
#include <string>
#include <unordered_map>
#include <phosg/Random.hh>
#include <phosg/Strings.hh>
#include <phosg/Time.hh>
@@ -336,7 +337,6 @@ static void server_command_cheat(shared_ptr<ServerState>, shared_ptr<Lobby> l,
c->options.infinite_tp = false;
c->options.switch_assist = false;
}
l->next_drop_item = PlayerInventoryItem();
}
}
@@ -1018,16 +1018,20 @@ static void server_command_item(shared_ptr<ServerState>, shared_ptr<Lobby> l,
return;
}
l->next_drop_item.clear();
PlayerInventoryItem item;
item.data.id = l->generate_item_id(c->lobby_client_id);
if (data.size() <= 12) {
memcpy(&l->next_drop_item.data.data1, data.data(), data.size());
memcpy(&item.data.data1, data.data(), data.size());
} else {
memcpy(&l->next_drop_item.data.data1, data.data(), 12);
memcpy(&l->next_drop_item.data.data2, data.data() + 12, data.size() - 12);
memcpy(&item.data.data1, data.data(), 12);
memcpy(&item.data.data2, data.data() + 12, data.size() - 12);
}
string name = name_for_item(l->next_drop_item.data, true);
send_text_message(c, u"$C7Next drop:\n" + decode_sjis(name));
l->add_item(item, c->area, c->x, c->z);
send_drop_stacked_item(l, item.data, c->area, c->x, c->z);
string name = name_for_item(item.data, true);
send_text_message(c, u"$C7Item created:\n" + decode_sjis(name));
}
static void proxy_command_item(shared_ptr<ServerState>,
@@ -1058,16 +1062,20 @@ static void proxy_command_item(shared_ptr<ServerState>,
return;
}
session.next_drop_item.clear();
PlayerInventoryItem item;
item.data.id = random_object<uint32_t>();
if (data.size() <= 12) {
memcpy(&session.next_drop_item.data.data1, data.data(), data.size());
memcpy(&item.data.data1, data.data(), data.size());
} else {
memcpy(&session.next_drop_item.data.data1, data.data(), 12);
memcpy(&session.next_drop_item.data.data2, data.data() + 12, data.size() - 12);
memcpy(&item.data.data1, data.data(), 12);
memcpy(&item.data.data2, data.data() + 12, data.size() - 12);
}
string name = name_for_item(session.next_drop_item.data, true);
send_text_message(session.client_channel, u"$C7Next drop:\n" + decode_sjis(name));
send_drop_stacked_item(session.client_channel, item.data, session.area, session.x, session.z);
send_drop_stacked_item(session.server_channel, item.data, session.area, session.x, session.z);
string name = name_for_item(item.data, true);
send_text_message(session.client_channel, u"$C7Item created:\n" + decode_sjis(name));
}
@@ -1103,6 +1111,7 @@ static const unordered_map<u16string, ChatCommandDefinition> chat_commands({
{u"$infhp", {server_command_infinite_hp, proxy_command_infinite_hp, u"Usage:\ninfhp"}},
{u"$inftp", {server_command_infinite_tp, proxy_command_infinite_tp, u"Usage:\ninftp"}},
{u"$item", {server_command_item, proxy_command_item, u"Usage:\nitem <item-code>"}},
{u"$i", {server_command_item, proxy_command_item, u"Usage:\ni <item-code>"}},
{u"$kick", {server_command_kick, nullptr, u"Usage:\nkick <name-or-number>"}},
{u"$li", {server_command_lobby_info, proxy_command_lobby_info, u"Usage:\nli"}},
{u"$maxlevel", {server_command_max_level, nullptr, u"Usage:\nmax_level <level>"}},
-1
View File
@@ -33,7 +33,6 @@ Lobby::Lobby(uint32_t id)
for (size_t x = 0; x < 12; x++) {
this->next_item_id[x] = 0x00010000 + 0x00200000 * x;
}
this->next_drop_item = PlayerInventoryItem();
}
void Lobby::reassign_leader_on_client_departure(size_t leaving_client_index) {
-1
View File
@@ -62,7 +62,6 @@ struct Lobby : public std::enable_shared_from_this<Lobby> {
std::vector<PSOEnemy> enemies;
std::array<uint32_t, 12> next_item_id;
uint32_t next_game_item_id;
PlayerInventoryItem next_drop_item;
std::unordered_map<uint32_t, FloorItem> item_id_to_floor_item;
parray<le_uint32_t, 0x20> variations;
+16 -30
View File
@@ -939,36 +939,6 @@ static HandlerResult S_6x(shared_ptr<ServerState>,
session.log.warning("Blocking subcommand 6x49 with invalid count");
return HandlerResult::Type::SUPPRESS;
}
} else if ((data[0] == 0x60) &&
session.next_drop_item.data.data1d[0] &&
(session.version != GameVersion::BB)) {
const auto& cmd = check_size_t<G_EnemyDropItemRequest_DC_6x60>(data,
sizeof(G_EnemyDropItemRequest_DC_6x60),
sizeof(G_EnemyDropItemRequest_PC_V3_BB_6x60));
session.next_drop_item.data.id = session.next_item_id++;
send_drop_item(session.server_channel, session.next_drop_item.data,
true, cmd.area, cmd.x, cmd.z, cmd.request_id);
send_drop_item(session.client_channel, session.next_drop_item.data,
true, cmd.area, cmd.x, cmd.z, cmd.request_id);
session.next_drop_item.clear();
return HandlerResult::Type::SUPPRESS;
// Note: This static_cast is required to make compilers not complain that
// the comparison is always false (which even happens in some environments
// if we use -0x5E... apparently char is unsigned on some systems, or
// std::string's char_type isn't char??)
} else if ((static_cast<uint8_t>(data[0]) == 0xA2) &&
session.next_drop_item.data.data1d[0] &&
(session.version != GameVersion::BB)) {
const auto& cmd = check_size_t<G_BoxItemDropRequest_6xA2>(data);
session.next_drop_item.data.id = session.next_item_id++;
send_drop_item(session.server_channel, session.next_drop_item.data,
false, cmd.area, cmd.x, cmd.z, cmd.request_id);
send_drop_item(session.client_channel, session.next_drop_item.data,
false, cmd.area, cmd.x, cmd.z, cmd.request_id);
session.next_drop_item.clear();
return HandlerResult::Type::SUPPRESS;
} else if ((static_cast<uint8_t>(data[0]) == 0xB5) &&
(session.version == GameVersion::GC) &&
(data.size() > 4)) {
@@ -1440,6 +1410,14 @@ constexpr on_command_t C_DGX_81 = &C_81<SC_SimpleMail_DC_V3_81>;
constexpr on_command_t C_P_81 = &C_81<SC_SimpleMail_PC_81>;
constexpr on_command_t C_B_81 = &C_81<SC_SimpleMail_BB_81>;
template <typename CmdT>
void C_6x_movement(ProxyServer::LinkedSession& session, const string& data) {
const auto& cmd = check_size_t<CmdT>(data);
session.x = cmd.x;
session.z = cmd.z;
}
template <typename SendGuildCardCmdT>
static HandlerResult C_6x(shared_ptr<ServerState> s,
ProxyServer::LinkedSession& session, uint16_t command, uint32_t flag, string& data) {
@@ -1464,6 +1442,14 @@ static HandlerResult C_6x(shared_ptr<ServerState> s,
send_player_stats_change(session.client_channel,
session.lobby_client_id, PlayerStatsChange::ADD_HP, 2550);
}
} else if (data[0] == 0x3E) {
C_6x_movement<G_StopAtPosition_6x3E>(session, data);
} else if (data[0] == 0x3F) {
C_6x_movement<G_SetPosition_6x3F>(session, data);
} else if (data[0] == 0x40) {
C_6x_movement<G_WalkToPosition_6x40>(session, data);
} else if (data[0] == 0x42) {
C_6x_movement<G_RunToPosition_6x42>(session, data);
} else if (data[0] == 0x48) {
if (session.options.infinite_tp) {
send_player_stats_change(session.client_channel,
+3
View File
@@ -486,6 +486,9 @@ ProxyServer::LinkedSession::LinkedSession(
lobby_players(12),
lobby_client_id(0),
leader_client_id(0),
area(0),
x(0.0),
z(0.0),
is_in_game(false) {
this->last_switch_enabled_command.header.subcommand = 0;
memset(this->prev_server_command_bytes, 0, sizeof(this->prev_server_command_bytes));
+2 -1
View File
@@ -65,7 +65,6 @@ public:
ClientConfigBB newserv_client_config;
std::deque<bool> should_forward_function_call_return_queue;
G_SwitchStateChanged_6x05 last_switch_enabled_command;
PlayerInventoryItem next_drop_item;
uint32_t next_item_id;
struct LobbyPlayer {
@@ -79,6 +78,8 @@ public:
size_t lobby_client_id;
size_t leader_client_id;
uint16_t area;
float x;
float z;
bool is_in_game;
std::shared_ptr<PSOBBMultiKeyDetectorEncryption> detector_crypt;
+3 -8
View File
@@ -881,13 +881,8 @@ static bool drop_item(
PlayerInventoryItem item;
// If there's an override item set (via the $item command), use that item code
if (l->next_drop_item.data.data1d[0]) {
item = l->next_drop_item;
l->next_drop_item.clear();
// If the game is BB, run the rare + common drop logic
} else if (l->version == GameVersion::BB) {
if (l->version == GameVersion::BB) {
if (!l->common_item_creator.get()) {
throw runtime_error("received box drop subcommand without item creator present");
}
@@ -932,8 +927,8 @@ static bool drop_item(
}
}
// If the game is not BB and there's no override item, forward the request to
// the leader instead of generating the item drop command
// If the game is not BB, forward the request to the leader instead of
// generating the item drop command
} else {
return false;
}
+7 -4
View File
@@ -1764,12 +1764,15 @@ void send_drop_item(shared_ptr<Lobby> l, const ItemData& item,
send_command_t(l, 0x60, 0x00, cmd);
}
// Notifies other players that a stack was split and part of it dropped (a new
// item was created)
void send_drop_stacked_item(Channel& ch, const ItemData& item,
uint8_t area, float x, float z) {
G_DropStackedItem_PC_V3_BB_6x5D cmd = {
{{0x5D, 0x0A, 0x0000}, area, 0, x, z, item}, 0};
ch.send(0x60, 0x00, &cmd, sizeof(cmd));
}
void send_drop_stacked_item(shared_ptr<Lobby> l, const ItemData& item,
uint8_t area, float x, float z) {
// TODO: Is this order correct? The original code sent {item, 0}, but it seems
// GC sends {0, item} (the last two fields in the struct are switched).
G_DropStackedItem_PC_V3_BB_6x5D cmd = {
{{0x5D, 0x0A, 0x0000}, area, 0, x, z, item}, 0};
send_command_t(l, 0x60, 0x00, cmd);
+2
View File
@@ -298,6 +298,8 @@ void send_drop_item(Channel& ch, const ItemData& item,
bool from_enemy, uint8_t area, float x, float z, uint16_t request_id);
void send_drop_item(std::shared_ptr<Lobby> l, const ItemData& item,
bool from_enemy, uint8_t area, float x, float z, uint16_t request_id);
void send_drop_stacked_item(Channel& ch, const ItemData& item,
uint8_t area, float x, float z);
void send_drop_stacked_item(std::shared_ptr<Lobby> l, const ItemData& item,
uint8_t area, float x, float z);
void send_pick_up_item(std::shared_ptr<Lobby> l, std::shared_ptr<Client> c, uint32_t id,
+11 -6
View File
@@ -5,6 +5,7 @@
#include <string.h>
#include <phosg/Strings.hh>
#include <phosg/Random.hh>
#include "ReceiveCommands.hh"
#include "ServerState.hh"
@@ -655,16 +656,20 @@ session with ID 17205AE4, run the command `on 17205AE4 sc 1D 00 04 00`.\n\
throw runtime_error("data too long");
}
session->next_drop_item.clear();
PlayerInventoryItem item;
item.data.id = random_object<uint32_t>();
if (data.size() <= 12) {
memcpy(&session->next_drop_item.data.data1, data.data(), data.size());
memcpy(&item.data.data1, data.data(), data.size());
} else {
memcpy(&session->next_drop_item.data.data1, data.data(), 12);
memcpy(&session->next_drop_item.data.data2, data.data() + 12, data.size() - 12);
memcpy(&item.data.data1, data.data(), 12);
memcpy(&item.data.data2, data.data() + 12, data.size() - 12);
}
string name = name_for_item(session->next_drop_item.data, true);
send_text_message(session->client_channel, u"$C7Next drop:\n" + decode_sjis(name));
send_drop_stacked_item(session->client_channel, item.data, session->area, session->x, session->z);
send_drop_stacked_item(session->server_channel, item.data, session->area, session->x, session->z);
string name = name_for_item(item.data, true);
send_text_message(session->client_channel, u"$C7Item created:\n" + decode_sjis(name));
} else if (command_name == "close-idle-sessions") {
size_t count = this->state->proxy_server->delete_disconnected_sessions();