Disabling buy item supported, few crash fixes

Fix  - buy from merchant can have the 'buy' button disabled
function buy_display_flags(Item, Spawn)
    return 128
end

charactersProperties -> character_properties

CREATE TABLE `character_properties` (
  `charid` int(10) unsigned NOT NULL DEFAULT 0,
  `propname` varchar(64) NOT NULL DEFAULT '',
  `propvalue` varchar(64) NOT NULL DEFAULT ''
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
drop table charactersProperties;
drop table charactersproperties;

- some misc crash fixes, sql escape issue, etc.
This commit is contained in:
Image 2021-03-23 22:08:29 -04:00
parent 852f035b45
commit 5656ad22ce
6 changed files with 40 additions and 15 deletions

View file

@ -3095,13 +3095,13 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
}
case COMMAND_USE: {
Spawn* target = cmdTarget;
if (target->IsWidget())
if (target && target->IsWidget())
((Widget*)target)->HandleUse(client, "use");
break;
}
case COMMAND_OPEN: {
Spawn* target = cmdTarget;
if (target->IsWidget())
if (target && target->IsWidget())
((Widget*)target)->HandleUse(client, "Open", WIDGET_TYPE_DOOR);
break;
}

View file

@ -603,6 +603,7 @@ extern MasterItemList master_item_list;
#define DISPLAY_FLAG_NO_GUILD_STATUS 8
#define DISPLAY_FLAG_NO_BUYBACK 16
#define DISPLAY_FLAG_NOT_FOR_SALE 64
#define DISPLAY_FLAG_NO_BUY 128 // disables buying on merchant 'buy' list
#pragma pack(1)
struct ItemStatsValues{

View file

@ -396,7 +396,7 @@ int EQ2Emu_lua_SendStateCommand(lua_State* state) {
}
else
{
spawn->GetZone()->SendStateCommand(spawn, new_state);
spawn->GetZone()->QueueStateCommandToClients(spawn->GetID(), new_state);
lua_interface->SetBooleanValue(state, true);
return 1;
}

View file

@ -1864,11 +1864,11 @@ bool WorldDatabase::UpdateCharacterTimeStamp(int32 account_id, int32 character_i
bool WorldDatabase::insertCharacterProperty(Client* client, char* propName, char* propValue) {
Query query;
string update_status = string("update charactersProperties set propvalue='%s' where charid=%i and propname='%s'");
string update_status = string("update character_properties set propvalue='%s' where charid=%i and propname='%s'");
query.RunQuery2(Q_UPDATE, update_status.c_str(), propValue, client->GetCharacterID(), propName);
if (!query.GetAffectedRows())
{
query.RunQuery2(Q_UPDATE, "insert into charactersProperties (charid, propname, propvalue) values(%i, '%s', '%s')", client->GetCharacterID(), propName, propValue);
query.RunQuery2(Q_UPDATE, "insert into character_properties (charid, propname, propvalue) values(%i, '%s', '%s')", client->GetCharacterID(), propName, propValue);
if (query.GetErrorNumber() && query.GetError() && query.GetErrorNumber() < 0xFFFFFFFF) {
LogWrite(WORLD__ERROR, 0, "World", "Error in insertCharacterProperty query '%s': %s", query.GetQuery(), query.GetError());
return false;
@ -1881,7 +1881,7 @@ bool WorldDatabase::loadCharacterProperties(Client* client) {
Query query;
MYSQL_ROW row;
int32 id = 0;
MYSQL_RES* result = query.RunQuery2(Q_SELECT, "SELECT propname, propvalue FROM charactersProperties where charid = %i", client->GetCharacterID());
MYSQL_RES* result = query.RunQuery2(Q_SELECT, "SELECT propname, propvalue FROM character_properties where charid = %i", client->GetCharacterID());
// no character found
if (result == NULL) {
LogWrite(PLAYER__ERROR, 0, "Player", "Error loading character properties for '%s'", client->GetPlayer()->GetName());
@ -2766,12 +2766,14 @@ void WorldDatabase::SaveZoneInfo(int32 zone_id, const char* field, const char* v
int32 WorldDatabase::GetZoneID(const char* name) {
int32 zone_id = 0;
Query query;
MYSQL_RES* result = query.RunQuery2(Q_SELECT, "SELECT `id` FROM zones WHERE `name`='%s'", name);
char* escaped = getEscapeString(name);
MYSQL_RES* result = query.RunQuery2(Q_SELECT, "SELECT `id` FROM zones WHERE `name`=\"%s\"", escaped);
if (result && mysql_num_rows(result) > 0) {
MYSQL_ROW row;
row = mysql_fetch_row(result);
zone_id = atoi(row[0]);
}
safe_delete_array(escaped);
return zone_id;
}
@ -4941,6 +4943,10 @@ int32 WorldDatabase::LoadQuests(){
total++;
master_quest_list.AddQuest(id, quest);
}
else
{
LogWrite(QUEST__ERROR, 5, "Quests", "\tFAILED LOADING QUEST: '%s' (%u), check that script file exists/permissions correct: %s", name, id, (script && strlen(script)) ? script : "Not Set, Missing!");
}
}
}
LogWrite(QUEST__DEBUG, 0, "Quest", "\tLoaded %i Quest(s)", total);

View file

@ -6570,7 +6570,11 @@ void Client::BuyBack(int32 item_id, int16 quantity) {
else
item->details.count = closest->quantity;
}
if (!player->item_list.HasFreeSlot() && !player->item_list.CanStack(item))
bool itemAdded = false;
sint64 dispFlags = 0;
if (item && item->GetItemScript() && lua_interface && lua_interface->RunItemScript(item->GetItemScript(), "buyback_display_flags", item, player, &dispFlags) && (dispFlags & DISPLAY_FLAG_NO_BUY))
SimpleMessage(CHANNEL_NARRATIVE, "You do not meet all the requirements to buy this item.");
else if (!player->item_list.HasFreeSlot() && !player->item_list.CanStack(item))
SimpleMessage(CHANNEL_COLOR_RED, "You do not have any slots available for this item.");
else if (player->RemoveCoins(closest->quantity * closest->price)) {
bool removed = false;
@ -6590,6 +6594,7 @@ void Client::BuyBack(int32 item_id, int16 quantity) {
closest->save_needed = true;
}
AddItem(item);
itemAdded = true;
//EQ2Packet* outapp = player->SendInventoryUpdate(GetVersion());
//if(outapp)
//QueuePacket(outapp);
@ -6604,6 +6609,9 @@ void Client::BuyBack(int32 item_id, int16 quantity) {
}
else
SimpleMessage(CHANNEL_COLOR_RED, "You cannot afford this item.");
if(!itemAdded)
safe_delete(item);
}
}
@ -6645,6 +6653,12 @@ void Client::BuyItem(int32 item_id, int16 quantity) {
if (quantity > total_available)
quantity = total_available;
}
sint64 dispFlags = 0;
if (master_item->GetItemScript() && lua_interface && lua_interface->RunItemScript(master_item->GetItemScript(), "buy_display_flags", master_item, player, &dispFlags) && (dispFlags & DISPLAY_FLAG_NO_BUY))
{
SimpleMessage(CHANNEL_NARRATIVE, "You do not meet all the requirements to buy this item.");
return;
}
if(quantity < 1)
{
SimpleMessage(CHANNEL_COLOR_RED, "Merchant does not have item for purchase (quantity < 1).");
@ -7019,6 +7033,10 @@ void Client::SendBuyMerchantList(bool sell) {
packet->setArrayDataByName("quantity", ItemInfo.quantity, i);
packet->setArrayDataByName("unknown5", 255, i);
packet->setArrayDataByName("stack_size2", item->stack_count, i);
sint64 dispFlags = 0;
if (item->GetItemScript() && lua_interface && lua_interface->RunItemScript(item->GetItemScript(), "buy_display_flags", item, player, &dispFlags))
packet->setArrayDataByName("display_flags", (int8)dispFlags, i);
std::string overrideValueStr;
// classic client isn't properly tracking this field, DoF we don't have it identified yet, but no field to cause any issues (can add later if identified)
@ -7275,6 +7293,11 @@ void Client::SendBuyBackList(bool sell) {
if (item_difficulty < 0)
item_difficulty *= -1;
packet->setArrayDataByName("item_difficulty", item_difficulty, i);
sint64 dispFlags = 0;
if (master_item->GetItemScript() && lua_interface && lua_interface->RunItemScript(master_item->GetItemScript(), "buyback_display_flags", master_item, player, &dispFlags))
packet->setArrayDataByName("display_flags", (int8)dispFlags, i);
if (buyback->quantity == 1)
packet->setArrayDataByName("quantity", 0xFFFF, i);
else

View file

@ -1882,9 +1882,6 @@ void ZoneServer::SendSpawnChanges(){
Spawn* spawn = 0;
MSpawnList.readlock(__FUNCTION__, __LINE__);
int32 max_updates = 100;
MutexList<int32>::iterator spawn_iter = changed_spawns.begin();
int count = 0;
while(spawn_iter.Next()){
@ -1895,9 +1892,6 @@ void ZoneServer::SendSpawnChanges(){
}
if (!spawn)
changed_spawns.Remove(spawn_iter->value);
if(count >= max_updates)
break;
}
//changed_spawns.clear() is not thread safe, advise we rely on what was removed and continue on, get any others in next batch
@ -1906,7 +1900,8 @@ void ZoneServer::SendSpawnChanges(){
MClientList.readlock(__FUNCTION__, __LINE__);
for (client_itr = clients.begin(); client_itr != clients.end(); client_itr++) {
client = *client_itr;
client->SendSpawnChanges(spawns_to_send);
if(client)
client->SendSpawnChanges(spawns_to_send);
}
MClientList.releasereadlock(__FUNCTION__, __LINE__);