- Fix - "placed" function now called on ItemScript placement in homes. The placed spawn will be the target field (after player).

- Fixed some additional lacking group member checks and bad returns inside mutex locks
- Fix  - set languages on sign/conversation, we can now set language in spawn_signs, language setting only garbles description, not title of spawn_signs
 * StartDialogConversation has a 9th parameter (after key2) for language (int8), 10th parameter is can_close (defaults to 1)
 * StartConversation has an 8th parameter (after key2) for language (int8), 9th prameter is can_close (defaults to 1)
 * spawn_signs table now supports the language parameter, db update:
	alter table spawn_signs add column language tinyint(3) unsigned default 0;
- Fixed AoM skill display for general skills, languages now display too, but we need to discover how to omit skill values
- /spawn details now includes sign language on the third page if the spawn is a sign.
This commit is contained in:
Emagi 2022-07-15 07:57:21 -04:00
parent 1184380240
commit d3819ec135
14 changed files with 121 additions and 79 deletions

View file

@ -415,10 +415,13 @@ Spell* Bot::GetHoTWardSpell() {
{
group->MGroupMembers.readlock(__FUNCTION__, __LINE__);
deque<GroupMemberInfo*>* members = group->GetMembers();
if(!members)
return 0;
for (int8 i = 0; i < members->size(); i++) {
Entity* member = members->at(i)->member;
if(!member)
continue;
int8 percent = 0;
if (member->GetHP() > 0)
percent = (int8)(((float)member->GetHP() / member->GetTotalHP()) * 100);

View file

@ -114,11 +114,10 @@ void Commands::Command_Bot(Client* client, Seperator* sep) {
group->MGroupMembers.readlock(__FUNCTION__, __LINE__);
deque<GroupMemberInfo*>* members = group->GetMembers();
if(!members)
return;
for (int8 i = 0; i < members->size(); i++) {
GroupMemberInfo* gmi2 = members->at(i);
if(!gmi2 || !gmi2->member)
continue;
if (gmi2->member->IsBot() && ((Bot*)gmi2->member)->GetOwner() == client->GetPlayer()) {
((Bot*)gmi2->member)->SetMainTank(target);
client->Message(CHANNEL_COMMAND_TEXT, "Setting main tank for %s to %s", gmi2->member->GetName(), target->GetName());

View file

@ -1247,8 +1247,7 @@ void Entity::HandleDeathExperienceDebt(Spawn* killer)
{
group->MGroupMembers.readlock(__FUNCTION__, __LINE__);
deque<GroupMemberInfo*>* members = group->GetMembers();
if(!members)
return;
int32 size = members->size();
float xpDebtPerMember = ruleDebt/(float)size;
deque<GroupMemberInfo*>::iterator itr;

View file

@ -4709,6 +4709,10 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
details3 += "Speed: " + to_string(spawn->GetSpeed()) + "\n";
details3 += "BaseSpeed: " + to_string(spawn->GetBaseSpeed()) + "\n";
if(spawn->IsSign()) {
details3 += "Sign Language: " + to_string(((Sign*)spawn)->GetLanguage()) + "\n";
}
if(spawn->IsEntity())
{
Entity* ent = (Entity*)spawn;

View file

@ -1019,6 +1019,12 @@ int EQ2Emu_lua_StartDialogConversation(lua_State* state) {
string mp3 = lua_interface->GetStringValue(state, 6);
int32 key1 = lua_interface->GetInt32Value(state, 7);
int32 key2 = lua_interface->GetInt32Value(state, 8);
int8 language = lua_interface->GetInt8Value(state, 9);
int numargs = lua_interface->GetNumberOfArgs(state);
int8 can_close = 1;
if(numargs > 9)
can_close = lua_interface->GetInt32Value(state, 10);
lua_interface->ResetFunctionStack(state);
if (conversation && text.length() > 0 && (spawn || item) && player && player->IsPlayer()) {
@ -1030,15 +1036,15 @@ int EQ2Emu_lua_StartDialogConversation(lua_State* state) {
type++;
if (mp3.length() > 0)
client->DisplayConversation((Entity*)spawn, type, conversation, const_cast<char*>(text.c_str()), mp3.c_str(), key1, key2);
client->DisplayConversation((Entity*)spawn, type, conversation, const_cast<char*>(text.c_str()), mp3.c_str(), key1, key2, language, can_close);
else
client->DisplayConversation((Entity*)spawn, type, conversation, const_cast<char*>(text.c_str()));
client->DisplayConversation((Entity*)spawn, type, conversation, const_cast<char*>(text.c_str()), nullptr, 0, 0, language, can_close);
}
else {
if (mp3.length() > 0)
client->DisplayConversation(item, conversation, const_cast<char*>(text.c_str()), type, mp3.c_str(), key1, key2);
client->DisplayConversation(item, conversation, const_cast<char*>(text.c_str()), type, mp3.c_str(), key1, key2, language, can_close);
else
client->DisplayConversation(item, conversation, const_cast<char*>(text.c_str()), type);
client->DisplayConversation(item, conversation, const_cast<char*>(text.c_str()), type, nullptr, 0, 0, language, can_close);
}
}
}
@ -1047,29 +1053,6 @@ int EQ2Emu_lua_StartDialogConversation(lua_State* state) {
return 0;
}
/*int EQ2Emu_lua_StartItemConversation(lua_State* state){
if(!lua_interface)
return 0;
vector<ConversationOption>* conversation = lua_interface->GetConversation(state);
Item* item = lua_interface->GetItem(state, 2);
Spawn* player = lua_interface->GetSpawn(state, 3);
string text = lua_interface->GetStringValue(state, 4);
string mp3 = lua_interface->GetStringValue(state, 5);
int32 key1 = lua_interface->GetInt32Value(state, 6);
int32 key2 = lua_interface->GetInt32Value(state, 7);
if(conversation && text.length() > 0 && item && player && player->IsPlayer()){
Client* client = player->GetZone()->GetClientBySpawn(player);
if(client){
if(mp3.length() > 0)
client->DisplayConversation(item, conversation, (char*)text.c_str(), mp3.c_str(), key1, key2);
else
client->DisplayConversation(item, conversation, (char*)text.c_str());
}
safe_delete(conversation);
}
return 0;
}*/
int EQ2Emu_lua_StartConversation(lua_State* state) {
if (!lua_interface)
return 0;
@ -1080,13 +1063,20 @@ int EQ2Emu_lua_StartConversation(lua_State* state) {
string mp3 = lua_interface->GetStringValue(state, 5);
int32 key1 = lua_interface->GetInt32Value(state, 6);
int32 key2 = lua_interface->GetInt32Value(state, 7);
int8 language = lua_interface->GetInt32Value(state, 8);
int numargs = lua_interface->GetNumberOfArgs(state);
int8 can_close = 1;
if(numargs > 8)
can_close = lua_interface->GetInt32Value(state, 9);
lua_interface->ResetFunctionStack(state);
if (conversation && conversation->size() > 0 && text.length() > 0 && source && player && player->IsPlayer()) {
Client* client = source->GetZone()->GetClientBySpawn(player);
if (mp3.length() > 0)
client->DisplayConversation(source, 1, conversation, text.c_str(), mp3.c_str(), key1, key2);
client->DisplayConversation(source, 1, conversation, text.c_str(), mp3.c_str(), key1, key2, language, can_close);
else
client->DisplayConversation(source, 1, conversation, text.c_str());
client->DisplayConversation(source, 1, conversation, text.c_str(), nullptr, 0, 0, language, can_close);
safe_delete(conversation);
lua_interface->SetConversationValue(state, NULL);
}

View file

@ -6100,6 +6100,10 @@ void Player::AddAAEntry(int16 template_id, int8 tab_id, int32 aa_id, int16 order
}
void Player::AddLanguage(int32 id, const char *name, bool save_needed){
Skill* skill = master_skill_list.GetSkillByName(name);
if(skill && !GetSkills()->HasSkill(skill->skill_id)) {
AddSkill(skill->skill_id, 1, skill->max_val, true);
}
// Check to see if the player already has the language
if (HasLanguage(id))
return;

View file

@ -48,6 +48,7 @@ Sign::Sign(){
include_location = false;
include_heading = false;
zone_id = 0;
language = 0;
}
Sign::~Sign(){
@ -150,6 +151,7 @@ Sign* Sign::Copy(){
new_spawn->SetOmittedByDBFlag(IsOmittedByDBFlag());
new_spawn->SetLootTier(GetLootTier());
new_spawn->SetLootDropType(GetLootDropType());
new_spawn->SetLanguage(GetLanguage());
return new_spawn;
}

View file

@ -66,7 +66,9 @@ public:
bool GetIncludeLocation();
void SetIncludeHeading(bool val);
bool GetIncludeHeading();
void SetLanguage(int8 in_language) { language = in_language; }
int8 GetLanguage() { return language; }
private:
string description;
string title;
@ -83,6 +85,7 @@ private:
float sign_distance;
bool include_location;
bool include_heading;
int8 language;
};
#endif

View file

@ -370,15 +370,31 @@ EQ2Packet* PlayerSkillList::GetSkillPacket(int16 version){
if (version <= 546 && skill->skill_type >= SKILL_TYPE_GENERAL) { //covert it to DOF types
packet->setArrayDataByName("type", skill->skill_type-2, i);
}
else
else if(version >= 60085 && skill->skill_type >= 12) {
packet->setArrayDataByName("type", skill->skill_type-1, i);
}
else {
packet->setArrayDataByName("type", skill->skill_type, i);
packet->setArrayDataByName("current_val", skill->current_val, i);
packet->setArrayDataByName("base_val", skill->current_val, i);// skill->
packet->setArrayDataByName("skill_delta", 0, i);// skill_with_bonuses- skill->current_val
packet->setArrayDataByName("skill_delta2", skill_max_with_bonuses - skill->max_val, i);// skill_max_with_bonuses - skill->max_val, i);
packet->setArrayDataByName("max_val", skill->max_val, i);
packet->setArrayDataByName("display_minval", skill->display, i);
packet->setArrayDataByName("display_maxval", skill->display, i);
}
int16 current_val = skill->current_val;
if(skill->skill_type == SKILL_TYPE_LANGUAGE) { // 13 is language in the DB?? 14 is the skill type though
packet->setArrayDataByName("language_unknown", skill->skill_id, i);
packet->setArrayDataByName("display_maxval", 1, i);
packet->setArrayDataByName("max_val", 1, i);
}
else {
packet->setArrayDataByName("max_val", skill->max_val, i);
packet->setArrayDataByName("display_minval", skill->display, i);
packet->setArrayDataByName("display_maxval", skill->display, i);
packet->setArrayDataByName("skill_delta", 0, i);// skill_with_bonuses- skill->current_val
packet->setArrayDataByName("skill_delta2", skill_max_with_bonuses - skill->max_val, i);// skill_max_with_bonuses - skill->max_val, i);
}
packet->setArrayDataByName("current_val", current_val, i);
packet->setArrayDataByName("base_val", current_val, i);
i++;
}
}

View file

@ -403,7 +403,6 @@ void Spawn::InitializeFooterPacketData(Player* player, PacketStruct* footer) {
footer->setDataByName("widget_z", widget->GetWidgetZ());
}
footer->setDataByName("widget_id", widget->GetWidgetID());
footer->setDataByName("unknown3c", 6);
}
else if (IsSign()){
Sign* sign = (Sign*)this;
@ -411,13 +410,16 @@ void Spawn::InitializeFooterPacketData(Player* player, PacketStruct* footer) {
footer->setDataByName("widget_x", sign->GetWidgetX());
footer->setDataByName("widget_y", sign->GetWidgetY());
footer->setDataByName("widget_z", sign->GetWidgetZ());
footer->setDataByName("unknown2b", 6);
if (sign->GetSignTitle())
footer->setMediumStringByName("title", sign->GetSignTitle());
if (sign->GetSignDescription())
footer->setMediumStringByName("description", sign->GetSignDescription());
footer->setDataByName("sign_distance", sign->GetSignDistance());
footer->setDataByName("show", 1);
// in live we see that the language is set when the player does not have it, otherwise its left as 00's.
if(!player->HasLanguage(sign->GetLanguage())) {
footer->setDataByName("language", sign->GetLanguage());
}
}
if ( IsPlayer())

View file

@ -2386,8 +2386,7 @@ void SpellProcess::GetSpellTargets(LuaSpell* luaspell)
{
group->MGroupMembers.readlock(__FUNCTION__, __LINE__);
deque<GroupMemberInfo*>* members = group->GetMembers();
if(!members)
return;
// iterate through players group members
for (itr = members->begin(); itr != members->end(); itr++)
{
@ -2436,8 +2435,7 @@ void SpellProcess::GetSpellTargets(LuaSpell* luaspell)
{
group->MGroupMembers.readlock(__FUNCTION__, __LINE__);
deque<GroupMemberInfo*>* members = group->GetMembers();
if(!members)
return;
Entity* group_member = 0;
for (itr = members->begin(); itr != members->end(); itr++) {
group_member = (*itr)->member;

View file

@ -1216,7 +1216,7 @@ void WorldDatabase::LoadSigns(ZoneServer* zone){
Sign* sign = 0;
int32 id = 0;
int32 total = 0;
MYSQL_RES* result = query.RunQuery2(Q_SELECT, "SELECT ss.spawn_id, s.name, s.model_type, s.size, s.show_command_icon, ss.widget_id, ss.widget_x, ss.widget_y, ss.widget_z, s.command_primary, s.command_secondary, s.collision_radius, ss.icon, ss.type, ss.title, ss.description, ss.sign_distance, ss.zone_id, ss.zone_x, ss.zone_y, ss.zone_z, ss.zone_heading, ss.include_heading, ss.include_location, s.transport_id, s.size_offset, s.display_hand_icon, s.visual_state, s.expansion_flag, s.holiday_flag, s.disable_sounds, s.merchant_min_level, s.merchant_max_level, s.aaxp_rewards, s.loot_tier, s.loot_drop_type\n"
MYSQL_RES* result = query.RunQuery2(Q_SELECT, "SELECT ss.spawn_id, s.name, s.model_type, s.size, s.show_command_icon, ss.widget_id, ss.widget_x, ss.widget_y, ss.widget_z, s.command_primary, s.command_secondary, s.collision_radius, ss.icon, ss.type, ss.title, ss.description, ss.sign_distance, ss.zone_id, ss.zone_x, ss.zone_y, ss.zone_z, ss.zone_heading, ss.include_heading, ss.include_location, s.transport_id, s.size_offset, s.display_hand_icon, s.visual_state, s.expansion_flag, s.holiday_flag, s.disable_sounds, s.merchant_min_level, s.merchant_max_level, s.aaxp_rewards, s.loot_tier, s.loot_drop_type, ss.language\n"
"FROM spawn s\n"
"INNER JOIN spawn_signs ss\n"
"ON s.id = ss.spawn_id\n"
@ -1295,6 +1295,8 @@ void WorldDatabase::LoadSigns(ZoneServer* zone){
sign->SetLootDropType(atoul(row[35]));
sign->SetLanguage(atoul(row[36]));
zone->AddSign(id, sign);
total++;
@ -3425,14 +3427,14 @@ bool WorldDatabase::SaveSpawnInfo(Spawn* spawn){
}
else if(spawn->IsSign()){
Sign* sign = (Sign*)spawn;
query.RunQuery2(Q_UPDATE, "update spawn_signs, spawn set name='%s', race=%i, model_type=%i, show_name=%i, attackable=%i, show_level=%i, show_command_icon=%i, display_hand_icon=%i, size=%i, hp=%u, power=%u, collision_radius=%i, command_primary=%u, command_secondary=%u, visual_state=%i, faction_id=%u, suffix ='%s', prefix='%s', last_name='%s', type='%s', zone_id = %u, widget_id = %u, title='%s', widget_x = %f, widget_y = %f, widget_z = %f, icon = %u, description='%s', sign_distance = %f, zone_x = %f, zone_y = %f, zone_z = %f, zone_heading = %f, include_heading = %u, include_location = %u, merchant_min_level = %u, merchant_max_level = %u where spawn_signs.spawn_id = spawn.id and spawn.id = %u",
query.RunQuery2(Q_UPDATE, "update spawn_signs, spawn set name='%s', race=%i, model_type=%i, show_name=%i, attackable=%i, show_level=%i, show_command_icon=%i, display_hand_icon=%i, size=%i, hp=%u, power=%u, collision_radius=%i, command_primary=%u, command_secondary=%u, visual_state=%i, faction_id=%u, suffix ='%s', prefix='%s', last_name='%s', type='%s', zone_id = %u, widget_id = %u, title='%s', widget_x = %f, widget_y = %f, widget_z = %f, icon = %u, description='%s', sign_distance = %f, zone_x = %f, zone_y = %f, zone_z = %f, zone_heading = %f, include_heading = %u, include_location = %u, merchant_min_level = %u, merchant_max_level = %u, language = %u where spawn_signs.spawn_id = spawn.id and spawn.id = %u",
name.c_str(), spawn->GetRace(), spawn->GetModelType(), spawn->appearance.display_name, spawn->appearance.attackable, spawn->appearance.show_level, spawn->appearance.show_command_icon, spawn->appearance.display_hand_icon, spawn->GetSize(),
spawn->GetTotalHP(), spawn->GetTotalPower(), spawn->GetCollisionRadius(), spawn->GetPrimaryCommandListID(), spawn->GetSecondaryCommandListID(), spawn->GetVisualState(), spawn->GetFactionID(),
suffix.c_str(), prefix.c_str(), last_name.c_str(), sign->GetSignType(), sign->GetSignZoneID(),
sign->GetWidgetID(), sign->GetSignTitle(), sign->GetWidgetX(), sign->GetWidgetY(), sign->GetWidgetZ(),
sign->GetIconValue(), sign->GetSignDescription(), sign->GetSignDistance(), sign->GetSignZoneX(),
sign->GetSignZoneY(), sign->GetSignZoneZ(), sign->GetSignZoneHeading(), sign->GetIncludeHeading(),
sign->GetIncludeLocation(), spawn->GetMerchantMinLevel(), spawn->GetMerchantMaxLevel(), spawn->GetDatabaseID());
sign->GetIncludeLocation(), spawn->GetMerchantMinLevel(), spawn->GetMerchantMaxLevel(), sign->GetLanguage(), spawn->GetDatabaseID());
}
}
if(query.GetErrorNumber() && query.GetError() && query.GetErrorNumber() < 0xFFFFFFFF){
@ -6391,7 +6393,7 @@ bool WorldDatabase::LoadSign(ZoneServer* zone, int32 spawn_id) {
Sign* sign = 0;
int32 id = 0;
DatabaseResult result;
database_new.Select(&result, "SELECT ss.spawn_id, s.name, s.model_type, s.size, s.show_command_icon, ss.widget_id, ss.widget_x, ss.widget_y, ss.widget_z, s.command_primary, s.command_secondary, s.collision_radius, ss.icon, ss.type, ss.title, ss.description, ss.sign_distance, ss.zone_id, ss.zone_x, ss.zone_y, ss.zone_z, ss.zone_heading, ss.include_heading, ss.include_location, s.transport_id, s.size_offset, s.display_hand_icon, s.visual_state, s.disable_sounds, s.merchant_min_level, s.merchant_max_level, s.aaxp_rewards, s.loot_tier, s.loot_drop_type\n"
database_new.Select(&result, "SELECT ss.spawn_id, s.name, s.model_type, s.size, s.show_command_icon, ss.widget_id, ss.widget_x, ss.widget_y, ss.widget_z, s.command_primary, s.command_secondary, s.collision_radius, ss.icon, ss.type, ss.title, ss.description, ss.sign_distance, ss.zone_id, ss.zone_x, ss.zone_y, ss.zone_z, ss.zone_heading, ss.include_heading, ss.include_location, s.transport_id, s.size_offset, s.display_hand_icon, s.visual_state, s.disable_sounds, s.merchant_min_level, s.merchant_max_level, s.aaxp_rewards, s.loot_tier, s.loot_drop_type, ss.language\n"
"FROM spawn s\n"
"INNER JOIN spawn_signs ss\n"
"ON ss.spawn_id = s.id\n"
@ -6452,6 +6454,9 @@ bool WorldDatabase::LoadSign(ZoneServer* zone, int32 spawn_id) {
sign->SetLootTier(result.GetInt32(32));
sign->SetLootDropType(result.GetInt32(33));
sign->SetLanguage(result.GetInt8(34));
zone->AddSign(id, sign);

View file

@ -1303,7 +1303,12 @@ bool Client::HandlePacket(EQApplicationPacket* app) {
int32 response_index = packet->getType_int32_ByName("response");
if (GetCurrentZone()) {
MConversation.readlock();
Spawn* spawn = conversation_spawns[conversation_id];
int32 spawn_id = conversation_spawns[conversation_id];
Spawn* spawn = nullptr;
if(spawn_id) {
spawn = GetCurrentZone()->GetSpawnByID(spawn_id);
}
Item* item = conversation_items[conversation_id];
MConversation.releasereadlock();
if (conversation_map.count(conversation_id) > 0 && conversation_map[conversation_id].count(response_index) > 0) {
@ -2549,6 +2554,8 @@ bool Client::HandleLootItem(Spawn* entity, Item* item) {
if(members) {
for (int8 i = 0; i < members->size(); i++) {
Entity* member = members->at(i)->member;
if(!member)
continue;
if ((member->GetZone() != this->GetPlayer()->GetZone()))
continue;
@ -5194,11 +5201,12 @@ void Client::CastGroupOrSelf(Entity* source, uint32 spellID, uint32 spellTier, f
{
group->MGroupMembers.readlock(__FUNCTION__, __LINE__);
deque<GroupMemberInfo*>* members = group->GetMembers();
if(!members)
return;
for (int8 i = 0; i < members->size(); i++) {
Entity* member = members->at(i)->member;
if(!member)
continue;
if (!member->Alive() || (member->GetZone() != source->GetZone()))
continue;
// if we have a radius provided then check if the group member is outside the radius or not
@ -6323,12 +6331,13 @@ void Client::GiveQuestReward(Quest* quest) {
RemovePlayerQuest(quest->GetQuestID(), true, false);
}
void Client::DisplayConversation(int32 conversation_id, int32 spawn_id, vector<ConversationOption>* conversations, const char* text, const char* mp3, int32 key1, int32 key2) {
void Client::DisplayConversation(int32 conversation_id, int32 spawn_id, vector<ConversationOption>* conversations, const char* text, const char* mp3, int32 key1, int32 key2, int8 language, int8 can_close) {
PacketStruct* packet = configReader.getStruct("WS_DialogOpen", GetVersion());
if (packet) {
packet->setDataByName("conversation_id", conversation_id);
packet->setDataByName("text", text);
packet->setDataByName("unknown2", 1);
packet->setDataByName("language", language); // default 0
packet->setDataByName("can_close", can_close); // default 1
conversation_map[conversation_id].clear();
if (conversations) {
packet->setArrayLengthByName("num_responses", conversations->size());
@ -6350,7 +6359,7 @@ void Client::DisplayConversation(int32 conversation_id, int32 spawn_id, vector<C
}
void Client::DisplayConversation(Item* item, vector<ConversationOption>* conversations, const char* text, int8 type, const char* mp3, int32 key1, int32 key2) {
void Client::DisplayConversation(Item* item, vector<ConversationOption>* conversations, const char* text, int8 type, const char* mp3, int32 key1, int32 key2, int8 language, int8 can_close) {
if (!item || !text || !conversations || conversations->size() == 0) {
return;
}
@ -6363,13 +6372,13 @@ void Client::DisplayConversation(Item* item, vector<ConversationOption>* convers
conversation_items[conversation_id] = item;
MConversation.releasewritelock();
if (type == 4)
DisplayConversation(conversation_id, player->GetIDWithPlayerSpawn(player), conversations, text, mp3, key1, key2);
DisplayConversation(conversation_id, player->GetIDWithPlayerSpawn(player), conversations, text, mp3, key1, key2, language, can_close);
else
DisplayConversation(conversation_id, 0xFFFFFFFF, conversations, text, mp3, key1, key2);
DisplayConversation(conversation_id, 0xFFFFFFFF, conversations, text, mp3, key1, key2, language, can_close);
}
void Client::DisplayConversation(Spawn* src, int8 type, vector<ConversationOption>* conversations, const char* text, const char* mp3, int32 key1, int32 key2) {
void Client::DisplayConversation(Spawn* src, int8 type, vector<ConversationOption>* conversations, const char* text, const char* mp3, int32 key1, int32 key2, int8 language, int8 can_close) {
if (!src || !(type == 1 || type == 2 || type == 3) || !text /*|| !conversations || conversations->size() == 0*/) {
return;
}
@ -6379,18 +6388,18 @@ void Client::DisplayConversation(Spawn* src, int8 type, vector<ConversationOptio
conversation_id = next_conversation_id;
}
MConversation.writelock();
conversation_spawns[conversation_id] = src;
conversation_spawns[conversation_id] = src->GetID();
MConversation.releasewritelock();
/* Spawns can start two different types of conversations.
* Type 1: The chat type with bubbles.
* Type 2: The dialog type with the blue box. */
if (type == 1)
DisplayConversation(conversation_id, player->GetIDWithPlayerSpawn(src), conversations, text, mp3, key1, key2);
DisplayConversation(conversation_id, player->GetIDWithPlayerSpawn(src), conversations, text, mp3, key1, key2, language, can_close);
else if (type == 2)
DisplayConversation(conversation_id, 0xFFFFFFFF, conversations, text, mp3, key1, key2);
DisplayConversation(conversation_id, 0xFFFFFFFF, conversations, text, mp3, key1, key2, language, can_close);
else //if (type == 3)
DisplayConversation(conversation_id, player->GetIDWithPlayerSpawn(player), conversations, text, mp3, key1, key2);
DisplayConversation(conversation_id, player->GetIDWithPlayerSpawn(player), conversations, text, mp3, key1, key2, language, can_close);
}
@ -6409,7 +6418,7 @@ void Client::CloseDialog(int32 conversation_id) {
conversation_items.erase(itr);
}
std::map<int32, Spawn*>::iterator itr2 = conversation_spawns.find(conversation_id);
std::map<int32, int32>::iterator itr2 = conversation_spawns.find(conversation_id);
while((itr2 = conversation_spawns.find(conversation_id)) != conversation_spawns.end())
{
@ -6423,9 +6432,9 @@ int32 Client::GetConversationID(Spawn* spawn, Item* item) {
int32 conversation_id = 0;
MConversation.readlock();
if (spawn) {
map<int32, Spawn*>::iterator itr;
map<int32, int32>::iterator itr;
for (itr = conversation_spawns.begin(); itr != conversation_spawns.end(); itr++) {
if (itr->second == spawn) {
if (itr->second == spawn->GetID()) {
conversation_id = itr->first;
break;
}
@ -10461,9 +10470,17 @@ bool Client::PopulateHouseSpawnFinalize()
query.RunQuery2(Q_INSERT, "insert into spawn_instance_data set spawn_id = %u, spawn_location_id = %u, pickup_item_id = %u, pickup_unique_item_id = %u", tmp->GetDatabaseID(), tmp->GetSpawnLocationID(), tmp->GetPickupItemID(), uniqueID);
}
database.DeleteItem(GetCharacterID(), uniqueItem, 0);
GetPlayer()->item_list.RemoveItem(uniqueItem, true);
QueuePacket(GetPlayer()->SendInventoryUpdate(GetVersion()));
if(lua_interface->RunItemScript(uniqueItem->GetItemScript(), "placed", uniqueItem, GetPlayer(), tmp))
{
uniqueItem = GetPlayer()->item_list.GetItemFromUniqueID(uniqueID);
}
if(uniqueItem) {
database.DeleteItem(GetCharacterID(), uniqueItem, 0);
GetPlayer()->item_list.RemoveItem(uniqueItem, true);
QueuePacket(GetPlayer()->SendInventoryUpdate(GetVersion()));
}
SetPlacementUniqueItemID(0);
}
return true;

View file

@ -285,9 +285,9 @@ public:
void AcceptQuestReward(Quest* quest, int32 item_id);
Quest* GetPendingQuestAcceptance(int32 item_id);
Quest* GetActiveQuest(int32 quest_id);
void DisplayConversation(int32 conversation_id, int32 spawn_id, vector<ConversationOption>* conversations, const char* text, const char* mp3, int32 key1, int32 key2);
void DisplayConversation(Item* item, vector<ConversationOption>* conversations, const char* text, int8 type, const char* mp3 = 0, int32 key1 = 0, int32 key2 = 0);
void DisplayConversation(Spawn* src, int8 type, vector<ConversationOption>* conversations, const char* text, const char* mp3 = 0, int32 key1 = 0, int32 key2 = 0);
void DisplayConversation(int32 conversation_id, int32 spawn_id, vector<ConversationOption>* conversations, const char* text, const char* mp3, int32 key1, int32 key2, int8 language = 0, int8 can_close = 1);
void DisplayConversation(Item* item, vector<ConversationOption>* conversations, const char* text, int8 type, const char* mp3 = 0, int32 key1 = 0, int32 key2 = 0, int8 language = 0, int8 can_close = 1);
void DisplayConversation(Spawn* src, int8 type, vector<ConversationOption>* conversations, const char* text, const char* mp3 = 0, int32 key1 = 0, int32 key2 = 0, int8 language = 0, int8 can_close = 1);
void CloseDialog(int32 conversation_id);
int32 GetConversationID(Spawn* spawn, Item* item);
void CombineSpawns(float radius, Spawn* spawn);
@ -568,7 +568,7 @@ private:
Spawn* combine_spawn;
int8 num_active_failures;
int32 next_conversation_id;
map<int32, Spawn*> conversation_spawns;
map<int32, int32> conversation_spawns;
map<int32, Item*> conversation_items;
Mutex MConversation;
map<int32, map<int8, string> > conversation_map;