KoS and earllier client fixes + server exploit fix
- Can now use equipped charms (previously did not work had to use from inventory) - Fixed charges not decrement when equipped for all clients (they had unlimited charges!!) - Fixed click / interacting with ground spawns, doors, so on. Some objects may need a default setting since the older clients don't send the entity command where new clients do. Made a fallback structure WS_EntityVerbsVerbBackup for when that happens.
This commit is contained in:
parent
aad24ca1e4
commit
13e10b315d
@ -3583,6 +3583,9 @@ to zero and treated like placeholders." />
|
||||
<Data ElementName="unknown2" Type="float" Size="1" />
|
||||
<Data ElementName="unknown3" Type="float" Size="1" />
|
||||
</Struct>
|
||||
<Struct Name="WS_EntityVerbsVerbBackup" ClientVersion="1" OpcodeName="OP_EntityVerbsVerbMsg">
|
||||
<Data ElementName="spawn_id" Type="int32" Size="1" />
|
||||
</Struct>
|
||||
<Struct Name="WS_EntityVerbsVerb" ClientVersion="1" OpcodeName="OP_EntityVerbsVerbMsg">
|
||||
<Data ElementName="spawn_id" Type="int32" Size="1" />
|
||||
<Data ElementName="command" Type="EQ2_16Bit_String" Size="1" />
|
||||
|
@ -2321,21 +2321,17 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
|
||||
}
|
||||
case COMMAND_USE_EQUIPPED_ITEM:{
|
||||
if (sep && sep->arg[0] && sep->IsNumber(0)){
|
||||
int32 slot_id = atoul(sep->arg[0]);
|
||||
int16 slot_id = 0;
|
||||
if(client->GetVersion() > 561) {
|
||||
slot_id = atoul(sep->arg[0]);
|
||||
}
|
||||
else if(strlen(sep->argplus[0]) > 0) { // the way that the arguments are pulled the length is truncated, it will always be 2. So just try to convert what we did get in the string to an integer
|
||||
const char* bufPtr = sep->argplus[0];
|
||||
slot_id = client->GetPlayer()->ConvertSlotFromClient(atoul(bufPtr), client->GetVersion());
|
||||
}
|
||||
Item* item = player->GetEquipmentList()->GetItem(slot_id);
|
||||
if (item && item->generic_info.usable && item->GetItemScript()) {
|
||||
if(!item->CheckFlag2(INDESTRUCTABLE) && item->generic_info.condition == 0) {
|
||||
client->SimpleMessage(CHANNEL_COLOR_RED, "This item is broken and must be repaired at a mender before it can be used");
|
||||
}
|
||||
else if (item->CheckFlag(EVIL_ONLY) && client->GetPlayer()->GetAlignment() != ALIGNMENT_EVIL) {
|
||||
client->Message(0, "%s requires an evil race.", item->name.c_str());
|
||||
}
|
||||
else if (item->CheckFlag(GOOD_ONLY) && client->GetPlayer()->GetAlignment() != ALIGNMENT_GOOD) {
|
||||
client->Message(0, "%s requires a good race.", item->name.c_str());
|
||||
}
|
||||
else {
|
||||
lua_interface->RunItemScript(item->GetItemScript(), "used", item, player, player->GetTarget());
|
||||
}
|
||||
client->UseItem(item, player->GetTarget(), true, slot_id);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -552,7 +552,7 @@ string GroundSpawn::GetHarvestSpellName() {
|
||||
}
|
||||
|
||||
void GroundSpawn::HandleUse(Client* client, string type){
|
||||
if(!client || type.length() == 0)
|
||||
if(!client || (client->GetVersion() > 561 && type.length() == 0)) // older clients do not send the type
|
||||
return;
|
||||
//The following check disables the use of the groundspawn if spawn access is not granted
|
||||
if (client) {
|
||||
@ -564,6 +564,9 @@ void GroundSpawn::HandleUse(Client* client, string type){
|
||||
}
|
||||
|
||||
MHarvestUse.lock();
|
||||
if(type == "" && client->GetVersion() <= 561)
|
||||
type = GetHarvestSpellType();
|
||||
|
||||
if (type == GetHarvestSpellType() && MeetsSpawnAccessRequirements(client->GetPlayer())) {
|
||||
Spell* spell = master_spell_list.GetSpellByName(GetHarvestSpellName().c_str());
|
||||
if (spell)
|
||||
|
@ -1960,73 +1960,80 @@ bool Client::HandlePacket(EQApplicationPacket* app) {
|
||||
LogWrite(OPCODE__DEBUG, 1, "Opcode", "Opcode 0x%X (%i): OP_EntityVerbsVerbMsg", opcode, opcode);
|
||||
PacketStruct* packet = configReader.getStruct("WS_EntityVerbsVerb", GetVersion());
|
||||
if (packet) {
|
||||
if (packet->LoadPacketData(app->pBuffer, app->size)) {
|
||||
int32 spawn_id = packet->getType_int32_ByName("spawn_id");
|
||||
Spawn* spawn = player->GetSpawnWithPlayerID(spawn_id); // fixed using GetTarget and the target was never set causing commands not to work
|
||||
player->SetTarget(spawn);
|
||||
if (spawn && !spawn->IsNPC() && !spawn->IsPlayer()) {
|
||||
string command = packet->getType_EQ2_16BitString_ByName("command").data;
|
||||
if(!packet->LoadPacketData(app->pBuffer, app->size)) {
|
||||
safe_delete(packet);
|
||||
packet = configReader.getStruct("WS_EntityVerbsVerbBackup", GetVersion());
|
||||
if(!packet->LoadPacketData(app->pBuffer, app->size)) {
|
||||
LogWrite(WORLD__ERROR, 0, "World", "Failed to properly load WS_EntityVerbsVerb for client.");
|
||||
safe_delete(packet);
|
||||
break;
|
||||
}
|
||||
}
|
||||
int32 spawn_id = packet->getType_int32_ByName("spawn_id");
|
||||
Spawn* spawn = player->GetSpawnWithPlayerID(spawn_id); // fixed using GetTarget and the target was never set causing commands not to work
|
||||
player->SetTarget(spawn);
|
||||
if (spawn && !spawn->IsNPC() && !spawn->IsPlayer()) {
|
||||
string command = packet->getType_EQ2_16BitString_ByName("command").data;
|
||||
|
||||
if (!HandleHouseEntityCommands(spawn, spawn_id, command))
|
||||
{
|
||||
if (EntityCommandPrecheck(spawn, command.c_str())) {
|
||||
if (spawn->IsGroundSpawn())
|
||||
((GroundSpawn*)spawn)->HandleUse(this, command);
|
||||
else if (spawn->IsObject())
|
||||
((Object*)spawn)->HandleUse(this, command);
|
||||
else if (spawn->IsWidget())
|
||||
((Widget*)spawn)->HandleUse(this, command);
|
||||
else if (spawn->IsSign())
|
||||
((Sign*)spawn)->HandleUse(this, command);
|
||||
}
|
||||
if (!HandleHouseEntityCommands(spawn, spawn_id, command))
|
||||
{
|
||||
if (EntityCommandPrecheck(spawn, command.c_str())) {
|
||||
if (spawn->IsGroundSpawn())
|
||||
((GroundSpawn*)spawn)->HandleUse(this, command);
|
||||
else if (spawn->IsObject())
|
||||
((Object*)spawn)->HandleUse(this, command);
|
||||
else if (spawn->IsWidget())
|
||||
((Widget*)spawn)->HandleUse(this, command);
|
||||
else if (spawn->IsSign())
|
||||
((Sign*)spawn)->HandleUse(this, command);
|
||||
}
|
||||
}
|
||||
else {
|
||||
EQ2_16BitString command = packet->getType_EQ2_16BitString_ByName("command");
|
||||
if (command.size > 0) {
|
||||
string command_name = command.data;
|
||||
if (command_name.find(" ") < 0xFFFFFFFF) {
|
||||
if (GetVersion() <= 561) { //this version uses commands in the form "Buy From Merchant" instead of buy_from_merchant
|
||||
string::size_type pos = command_name.find(" ");
|
||||
while (pos != string::npos) {
|
||||
command_name.replace(pos, 1, "_");
|
||||
pos = command_name.find(" ");
|
||||
}
|
||||
}
|
||||
else {
|
||||
EQ2_16BitString command = packet->getType_EQ2_16BitString_ByName("command");
|
||||
if (command.size > 0) {
|
||||
string command_name = command.data;
|
||||
if (command_name.find(" ") < 0xFFFFFFFF) {
|
||||
if (GetVersion() <= 561) { //this version uses commands in the form "Buy From Merchant" instead of buy_from_merchant
|
||||
string::size_type pos = command_name.find(" ");
|
||||
while (pos != string::npos) {
|
||||
command_name.replace(pos, 1, "_");
|
||||
pos = command_name.find(" ");
|
||||
}
|
||||
else
|
||||
command_name = command_name.substr(0, command_name.find(" "));
|
||||
}
|
||||
int32 handler = commands.GetCommandHandler(command_name.c_str());
|
||||
if (handler != 0xFFFFFFFF) {
|
||||
if (command.data == command_name) {
|
||||
command.data = "";
|
||||
command.size = 0;
|
||||
}
|
||||
else {
|
||||
command.data = command.data.substr(command.data.find(" ") + 1);
|
||||
command.size = command.data.length();
|
||||
}
|
||||
commands.Process(handler, &command, this);
|
||||
else
|
||||
command_name = command_name.substr(0, command_name.find(" "));
|
||||
}
|
||||
int32 handler = commands.GetCommandHandler(command_name.c_str());
|
||||
if (handler != 0xFFFFFFFF) {
|
||||
if (command.data == command_name) {
|
||||
command.data = "";
|
||||
command.size = 0;
|
||||
}
|
||||
else {
|
||||
if (spawn && spawn->IsNPC()) {
|
||||
if (EntityCommandPrecheck(spawn, command.data.c_str())) {
|
||||
if (!((NPC*)spawn)->HandleUse(this, command.data)) {
|
||||
command_name = command.data;
|
||||
string::size_type pos = command_name.find(" ");
|
||||
while (pos != string::npos) {
|
||||
command_name.replace(pos, 1, "_");
|
||||
pos = command_name.find(" ");
|
||||
}
|
||||
if (!((NPC*)spawn)->HandleUse(this, command_name)) { //convert the spaces to underscores and see if that makes a difference
|
||||
LogWrite(WORLD__ERROR, 0, "World", "Unhandled command in OP_EntityVerbsVerbMsg: %s", command.data.c_str());
|
||||
}
|
||||
command.data = command.data.substr(command.data.find(" ") + 1);
|
||||
command.size = command.data.length();
|
||||
}
|
||||
commands.Process(handler, &command, this);
|
||||
}
|
||||
else {
|
||||
if (spawn && spawn->IsNPC()) {
|
||||
if (EntityCommandPrecheck(spawn, command.data.c_str())) {
|
||||
if (!((NPC*)spawn)->HandleUse(this, command.data)) {
|
||||
command_name = command.data;
|
||||
string::size_type pos = command_name.find(" ");
|
||||
while (pos != string::npos) {
|
||||
command_name.replace(pos, 1, "_");
|
||||
pos = command_name.find(" ");
|
||||
}
|
||||
if (!((NPC*)spawn)->HandleUse(this, command_name)) { //convert the spaces to underscores and see if that makes a difference
|
||||
LogWrite(WORLD__ERROR, 0, "World", "Unhandled command in OP_EntityVerbsVerbMsg: %s", command.data.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
LogWrite(WORLD__ERROR, 0, "World", "Unknown command in OP_EntityVerbsVerbMsg: %s", command.data.c_str());
|
||||
}
|
||||
else
|
||||
LogWrite(WORLD__ERROR, 0, "World", "Unknown command in OP_EntityVerbsVerbMsg: %s", command.data.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -12819,7 +12826,7 @@ void Client::SetPlayer(Player* new_player) {
|
||||
player->SetClient(this);
|
||||
}
|
||||
|
||||
bool Client::UseItem(Item* item, Spawn* target) {
|
||||
bool Client::UseItem(Item* item, Spawn* target, bool equippedItem, int16 equipSlot) {
|
||||
if (item && item->GetItemScript()) {
|
||||
int16 item_index = item->details.index;
|
||||
if (!item->CheckFlag2(INDESTRUCTABLE) && item->generic_info.condition == 0) {
|
||||
@ -12843,7 +12850,10 @@ bool Client::UseItem(Item* item, Spawn* target) {
|
||||
if (lua_interface->RunItemScript(item->GetItemScript(), "used", item, player, target, &flags) && flags >= 0)
|
||||
{
|
||||
//reobtain item make sure it wasn't removed
|
||||
item = player->item_list.GetItemFromIndex(item_index);
|
||||
if(equippedItem)
|
||||
item = player->GetEquipmentList()->GetItem(equipSlot);
|
||||
else
|
||||
item = player->item_list.GetItemFromIndex(item_index);
|
||||
if (!item) {
|
||||
LogWrite(PLAYER__WARNING, 0, "Command", "%s: Item %s (%i) was used, however after the item looks to be removed.", GetPlayer()->GetName(), itemName.c_str(), item_id);
|
||||
return true;
|
||||
@ -12857,10 +12867,21 @@ bool Client::UseItem(Item* item, Spawn* target) {
|
||||
{
|
||||
item->details.count--; // charges
|
||||
item->save_needed = true;
|
||||
QueuePacket(item->serialize(GetVersion(), false, GetPlayer()));
|
||||
if(equippedItem) {
|
||||
QueuePacket(player->GetEquipmentList()->serialize(GetVersion(), player));
|
||||
QueuePacket(item->serialize(version, false, player));
|
||||
}
|
||||
else {
|
||||
QueuePacket(item->serialize(GetVersion(), false, GetPlayer()));
|
||||
}
|
||||
if (!item->details.count) {
|
||||
Message(CHANNEL_NARRATIVE, "%s is out of charges. It has been removed.", item->name.c_str());
|
||||
RemoveItem(item, 1); // end of a set of charges OR an item that uses a stack count of actual item quantity
|
||||
if(equippedItem) {
|
||||
Message(CHANNEL_NARRATIVE, "%s is out of charges.", item->name.c_str());
|
||||
}
|
||||
else {
|
||||
Message(CHANNEL_NARRATIVE, "%s is out of charges. It has been removed.", item->name.c_str());
|
||||
RemoveItem(item, 1); // end of a set of charges OR an item that uses a stack count of actual item quantity
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -670,7 +670,7 @@ public:
|
||||
zoning_h = h;
|
||||
}
|
||||
|
||||
bool UseItem(Item* item, Spawn* target = nullptr);
|
||||
bool UseItem(Item* item, Spawn* target = nullptr, bool equippedItem = false, int16 equipSlot = 0);
|
||||
|
||||
void SendPlayFlavor(Spawn* spawn, int8 language, VoiceOverStruct* non_garble, VoiceOverStruct* garble, bool success = false, bool garble_success = false);
|
||||
void SaveQuestRewardData(bool force_refresh = false);
|
||||
|
Loading…
x
Reference in New Issue
Block a user