make $item more powerful
This commit is contained in:
+22
-13
@@ -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>"}},
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
@@ -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,
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user