Fix #527, blue and debt xp, Fix #523 db translation of emotes table to action_state, action_state_str added to spawns_npc table
This commit is contained in:
parent
1646afdf4e
commit
b924495ba3
11 changed files with 156 additions and 28 deletions
58
DB/updates/emotes.sql
Normal file
58
DB/updates/emotes.sql
Normal file
File diff suppressed because one or more lines are too long
|
@ -342,6 +342,10 @@ void Entity::MapInfoStruct()
|
|||
get_int8_funcs["engaged_encounter"] = l::bind(&InfoStruct::get_engaged_encounter, &info_struct);
|
||||
|
||||
get_int8_funcs["first_world_login"] = l::bind(&InfoStruct::get_first_world_login, &info_struct);
|
||||
|
||||
get_int8_funcs["reload_player_spells"] = l::bind(&InfoStruct::get_reload_player_spells, &info_struct);
|
||||
|
||||
get_string_funcs["action_state"] = l::bind(&InfoStruct::get_action_state, &info_struct);
|
||||
|
||||
/** SETS **/
|
||||
set_string_funcs["name"] = l::bind(&InfoStruct::set_name, &info_struct, l::_1);
|
||||
|
@ -529,6 +533,10 @@ void Entity::MapInfoStruct()
|
|||
set_int8_funcs["engaged_encounter"] = l::bind(&InfoStruct::set_engaged_encounter, &info_struct, l::_1);
|
||||
|
||||
set_int8_funcs["first_world_login"] = l::bind(&InfoStruct::set_first_world_login, &info_struct, l::_1);
|
||||
|
||||
set_int8_funcs["reload_player_spells"] = l::bind(&InfoStruct::set_reload_player_spells, &info_struct, l::_1);
|
||||
|
||||
set_string_funcs["action_state"] = l::bind(&InfoStruct::set_action_state, &info_struct, l::_1);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -278,6 +278,8 @@ struct InfoStruct{
|
|||
|
||||
first_world_login_ = 0;
|
||||
reload_player_spells_ = 0;
|
||||
|
||||
action_state_ = std::string("");
|
||||
}
|
||||
|
||||
|
||||
|
@ -467,6 +469,8 @@ struct InfoStruct{
|
|||
|
||||
first_world_login_ = oldStruct->get_first_world_login();
|
||||
reload_player_spells_ = oldStruct->get_reload_player_spells();
|
||||
|
||||
action_state_ = oldStruct->get_action_state();
|
||||
|
||||
}
|
||||
//mutable std::shared_mutex mutex_;
|
||||
|
@ -675,6 +679,8 @@ struct InfoStruct{
|
|||
|
||||
int8 get_reload_player_spells() { std::lock_guard<std::mutex> lk(classMutex); return reload_player_spells_; }
|
||||
|
||||
std::string get_action_state() { std::lock_guard<std::mutex> lk(classMutex); return action_state_; }
|
||||
|
||||
void set_name(std::string value) { std::lock_guard<std::mutex> lk(classMutex); name_ = value; }
|
||||
|
||||
void set_deity(std::string value) { std::lock_guard<std::mutex> lk(classMutex); deity_ = value; }
|
||||
|
@ -779,7 +785,7 @@ struct InfoStruct{
|
|||
void set_xp(int32 value) { std::lock_guard<std::mutex> lk(classMutex); xp_ = value; }
|
||||
void set_xp_needed(int32 value) { std::lock_guard<std::mutex> lk(classMutex); xp_needed_ = value; }
|
||||
|
||||
void set_xp_debt(float value) { std::lock_guard<std::mutex> lk(classMutex); xp_debt_ = value; }
|
||||
void set_xp_debt(float value) { std::lock_guard<std::mutex> lk(classMutex); if(std::isnan(value)) value = 0.0f; xp_debt_ = value; }
|
||||
|
||||
void set_xp_yellow(int16 value) { std::lock_guard<std::mutex> lk(classMutex); xp_yellow_ = value; }
|
||||
void set_xp_blue(int16 value) { std::lock_guard<std::mutex> lk(classMutex); xp_blue_ = value; }
|
||||
|
@ -967,6 +973,8 @@ struct InfoStruct{
|
|||
|
||||
void set_reload_player_spells(int8 value) { std::lock_guard<std::mutex> lk(classMutex); reload_player_spells_ = value; }
|
||||
|
||||
void set_action_state(std::string value) { std::lock_guard<std::mutex> lk(classMutex); action_state_ = value; }
|
||||
|
||||
void ResetEffects(Spawn* spawn)
|
||||
{
|
||||
for(int i=0;i<45;i++){
|
||||
|
@ -1174,6 +1182,8 @@ private:
|
|||
int8 first_world_login_;
|
||||
int8 reload_player_spells_;
|
||||
|
||||
std::string action_state_;
|
||||
|
||||
// when PacketStruct is fixed for C++17 this should become a shared_mutex and handle read/write lock
|
||||
std::mutex classMutex;
|
||||
};
|
||||
|
|
|
@ -259,9 +259,14 @@ PlayerInfo* Player::GetPlayerInfo(){
|
|||
void PlayerInfo::CalculateXPPercentages(){
|
||||
int32 xp_needed = info_struct->get_xp_needed();
|
||||
if(xp_needed > 0){
|
||||
float percentage = ((double)info_struct->get_xp() / xp_needed) * 1000;
|
||||
info_struct->set_xp_yellow((int16)percentage);
|
||||
info_struct->set_xp_blue((int16)(percentage-info_struct->get_xp_yellow())*1000);
|
||||
double div_percent = ((double)info_struct->get_xp() / xp_needed) * 100.0;
|
||||
int16 percentage = (int16)(div_percent) * 10;
|
||||
double whole, fractional = 0.0;
|
||||
fractional = std::modf(div_percent, &whole);
|
||||
info_struct->set_xp_yellow(percentage);
|
||||
info_struct->set_xp_blue((int16)(fractional * 1000));
|
||||
|
||||
// vitality bars probably need a revisit
|
||||
info_struct->set_xp_blue_vitality_bar(0);
|
||||
info_struct->set_xp_yellow_vitality_bar(0);
|
||||
if(player->GetXPVitality() > 0){
|
||||
|
@ -759,7 +764,9 @@ EQ2Packet* PlayerInfo::serialize(int16 version, int16 modifyPos, int32 modifyVal
|
|||
}
|
||||
else
|
||||
{
|
||||
packet->setDataByName("exp_debt", (int16)(info_struct->get_xp_debt()/10.0f));//95= 9500% //confirmed DoV
|
||||
double currentPctOfLevel = (double)info_struct->get_xp() / (double)info_struct->get_xp_needed();
|
||||
double neededPctAdvanceOutOfDebt = (currentPctOfLevel + ((double)info_struct->get_xp_debt() / 100.0)) * 1000.0;
|
||||
packet->setDataByName("exp_debt", (int16)(neededPctAdvanceOutOfDebt));//95= 9500% //confirmed DoV
|
||||
}
|
||||
|
||||
packet->setDataByName("current_trade_xp", info_struct->get_ts_xp());// confirmed DoV
|
||||
|
@ -2441,8 +2448,6 @@ void Player::RemovePlayerSkill(int32 skill_id, bool save) {
|
|||
Skill* skill = skill_list.GetSkill(skill_id);
|
||||
if (skill)
|
||||
RemoveSkillFromDB(skill, save);
|
||||
|
||||
safe_delete(skill);
|
||||
}
|
||||
|
||||
void Player::RemoveSkillFromDB(Skill* skill, bool save) {
|
||||
|
@ -3970,7 +3975,7 @@ void Player::CalculateOfflineDebtRecovery(int32 unix_timestamp)
|
|||
if(unix_timestamp < 1 || xpDebt == 0.0f)
|
||||
return;
|
||||
|
||||
uint32 diff = (Timer::GetCurrentTime2() - unix_timestamp)/1000;
|
||||
uint32 diff = (Timer::GetUnixTimeStamp() - unix_timestamp)/1000;
|
||||
|
||||
float recoveryDebtPercentage = rule_manager.GetGlobalRule(R_Combat, ExperienceDebtRecoveryPercent)->GetFloat()/100.0f;
|
||||
int32 recoveryPeriodSeconds = rule_manager.GetGlobalRule(R_Combat, ExperienceDebtRecoveryPeriod)->GetInt32();
|
||||
|
|
|
@ -47,6 +47,7 @@ Skill::Skill(){
|
|||
skill_type = 0;
|
||||
display = 0;
|
||||
save_needed = false;
|
||||
active_skill = true;
|
||||
}
|
||||
|
||||
Skill::Skill(Skill* skill){
|
||||
|
@ -60,6 +61,7 @@ Skill::Skill(Skill* skill){
|
|||
name = skill->name;
|
||||
description = skill->description;
|
||||
save_needed = false;
|
||||
active_skill = true;
|
||||
}
|
||||
|
||||
map<int32, Skill*>* MasterSkillList::GetAllSkills(){
|
||||
|
@ -145,6 +147,7 @@ PlayerSkillList::~PlayerSkillList(){
|
|||
}
|
||||
|
||||
void PlayerSkillList::AddSkill(Skill* new_skill){
|
||||
std::unique_lock lock(MPlayerSkills);
|
||||
Skill* tmpSkill = nullptr;
|
||||
if(skills.count(new_skill->skill_id)) {
|
||||
tmpSkill = skills[new_skill->skill_id];
|
||||
|
@ -154,12 +157,15 @@ void PlayerSkillList::AddSkill(Skill* new_skill){
|
|||
lua_interface->SetLuaUserDataStale(tmpSkill);
|
||||
safe_delete(tmpSkill);
|
||||
}
|
||||
name_skill_map.clear();
|
||||
}
|
||||
|
||||
void PlayerSkillList::RemoveSkill(Skill* skill) {
|
||||
std::unique_lock lock(MPlayerSkills);
|
||||
if (skill) {
|
||||
lua_interface->SetLuaUserDataStale(skill);
|
||||
skills.erase(skill->skill_id);
|
||||
skill->active_skill = false;
|
||||
name_skill_map.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -199,11 +205,13 @@ void PlayerSkillList::IncreaseAllSkillCaps(int16 value){
|
|||
}
|
||||
|
||||
bool PlayerSkillList::HasSkill(int32 skill_id){
|
||||
return (skills.count(skill_id) > 0);
|
||||
std::shared_lock lock(MPlayerSkills);
|
||||
return (skills.count(skill_id) > 0 && skills[skill_id]->active_skill);
|
||||
}
|
||||
|
||||
Skill* PlayerSkillList::GetSkill(int32 skill_id){
|
||||
if(skills.count(skill_id) > 0)
|
||||
std::shared_lock lock(MPlayerSkills);
|
||||
if(skills.count(skill_id) > 0 && skills[skill_id]->active_skill)
|
||||
return skills[skill_id];
|
||||
else
|
||||
return 0;
|
||||
|
@ -337,20 +345,27 @@ int16 PlayerSkillList::CalculateSkillMaxValue(int32 skill_id, int16 max_val) {
|
|||
}
|
||||
|
||||
EQ2Packet* PlayerSkillList::GetSkillPacket(int16 version){
|
||||
std::shared_lock lock(MPlayerSkills);
|
||||
PacketStruct* packet = configReader.getStruct("WS_UpdateSkillBook", version);
|
||||
if(packet){
|
||||
int16 skill_count = 0;
|
||||
map<int32, Skill*>::iterator itr;
|
||||
for (itr = skills.begin(); itr != skills.end(); itr++) {
|
||||
if (itr->second && itr->second->active_skill)
|
||||
skill_count++;
|
||||
}
|
||||
int16 size = 0;
|
||||
if (version > 546) {
|
||||
size = 21 * skills.size() + 8;
|
||||
size = 21 * skill_count + 8;
|
||||
}
|
||||
else if (version <= 283) {
|
||||
size = 12 * skills.size() + 6;
|
||||
size = 12 * skill_count + 6;
|
||||
}
|
||||
else if (version <= 546) {
|
||||
size = 21 * skills.size() + 7;
|
||||
size = 21 * skill_count + 7;
|
||||
}
|
||||
|
||||
if (skills.size() > packet_count) {
|
||||
if (skill_count > packet_count) {
|
||||
uchar* tmp = 0;
|
||||
if (orig_packet) {
|
||||
tmp = new uchar[size];
|
||||
|
@ -367,15 +382,14 @@ EQ2Packet* PlayerSkillList::GetSkillPacket(int16 version){
|
|||
xor_packet = new uchar[size];
|
||||
memset(xor_packet, 0, size);
|
||||
}
|
||||
packet_count = skills.size();
|
||||
packet_count = skill_count;
|
||||
orig_packet_size = size;
|
||||
packet->setArrayLengthByName("skill_count", skills.size());
|
||||
map<int32, Skill*>::iterator itr;
|
||||
packet->setArrayLengthByName("skill_count", skill_count);
|
||||
Skill* skill = 0;
|
||||
int32 i=0;
|
||||
for(itr = skills.begin(); itr != skills.end(); itr++){
|
||||
skill = itr->second;
|
||||
if(skill){
|
||||
if(skill && skill->active_skill){
|
||||
int16 skill_max_with_bonuses = CalculateSkillMaxValue(skill->skill_id, skill->max_val);
|
||||
int16 skill_with_bonuses = int(CalculateSkillValue(skill->skill_id, skill->current_val));
|
||||
packet->setArrayDataByName("skill_id", skill->skill_id, i);
|
||||
|
@ -406,8 +420,8 @@ EQ2Packet* PlayerSkillList::GetSkillPacket(int16 version){
|
|||
|
||||
packet->setArrayDataByName("current_val", current_val, i);
|
||||
packet->setArrayDataByName("base_val", current_val, i);
|
||||
i++;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
int8 offset = 1;
|
||||
if (version <= 283)
|
||||
|
@ -437,6 +451,7 @@ bool PlayerSkillList::CheckSkillIncrease(Skill* skill){
|
|||
}
|
||||
|
||||
Skill* PlayerSkillList::GetSkillByName(const char* name){
|
||||
std::shared_lock lock(MPlayerSkills);
|
||||
if(name_skill_map.size() == 0){
|
||||
map<int32, Skill*>::iterator itr;
|
||||
Skill* skill = 0;
|
||||
|
@ -452,6 +467,7 @@ Skill* PlayerSkillList::GetSkillByName(const char* name){
|
|||
}
|
||||
|
||||
vector<Skill*>* PlayerSkillList::GetSaveNeededSkills(){
|
||||
std::shared_lock lock(MPlayerSkills);
|
||||
vector<Skill*>* ret = new vector<Skill*>;
|
||||
map<int32, Skill*>::iterator itr;
|
||||
for(itr = skills.begin(); itr != skills.end(); itr++){
|
||||
|
|
|
@ -21,6 +21,9 @@
|
|||
#define __EQ2_SKILLS_H__
|
||||
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <shared_mutex>
|
||||
|
||||
#include "../common/ConfigReader.h"
|
||||
#include "../common/types.h"
|
||||
#include "MutexMap.h"
|
||||
|
@ -97,6 +100,7 @@ public:
|
|||
EQ2_16BitString name;
|
||||
EQ2_16BitString description;
|
||||
bool save_needed;
|
||||
bool active_skill;
|
||||
int CheckDisarmSkill(int16 targetLevel, int8 chest_difficulty=0);
|
||||
};
|
||||
|
||||
|
@ -161,6 +165,7 @@ public:
|
|||
void ResetPackets();
|
||||
private:
|
||||
volatile bool has_updates;
|
||||
mutable std::shared_mutex MPlayerSkills;
|
||||
Mutex MSkillUpdates;
|
||||
int16 packet_count;
|
||||
uchar* orig_packet;
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "Bots/Bot.h"
|
||||
#include "Zone/raycast_mesh.h"
|
||||
#include "RaceTypes/RaceTypes.h"
|
||||
#include "VisualStates.h"
|
||||
|
||||
extern ConfigReader configReader;
|
||||
extern RuleManager rule_manager;
|
||||
|
@ -40,6 +41,7 @@ extern World world;
|
|||
extern ZoneList zone_list;
|
||||
extern MasterRaceTypeList race_types_list;
|
||||
extern LuaInterface* lua_interface;
|
||||
extern VisualStates visual_states;
|
||||
|
||||
Spawn::Spawn(){
|
||||
loot_coins = 0;
|
||||
|
@ -2403,8 +2405,19 @@ void Spawn::InitializeInfoPacketData(Player* spawn, PacketStruct* packet) {
|
|||
|
||||
if (GetTempActionState() >= 0)
|
||||
packet->setDataByName("action_state", GetTempActionState());
|
||||
else
|
||||
packet->setDataByName("action_state", appearance.action_state);
|
||||
else {
|
||||
Client* client = spawn->GetClient();
|
||||
int16 action_state = appearance.action_state;
|
||||
if(IsEntity() && client) {
|
||||
std::string actionState = ((Entity*)this)->GetInfoStruct()->get_action_state();
|
||||
if(actionState.size() > 0) {
|
||||
Emote* emote = visual_states.FindEmote(actionState, client->GetVersion());
|
||||
if(emote != NULL)
|
||||
action_state = emote->GetVisualState();
|
||||
}
|
||||
}
|
||||
packet->setDataByName("action_state", action_state);
|
||||
}
|
||||
|
||||
bool scaredOfPlayer = false;
|
||||
|
||||
|
|
|
@ -1282,8 +1282,8 @@ void SpellProcess::ProcessSpell(ZoneServer* zone, Spell* spell, Entity* caster,
|
|||
LogWrite(SPELL__DEBUG, 1, "Spell", "%s: Target Enemy (%s) and Max AE Targets = 0.", spell->GetName(), target->GetName());
|
||||
|
||||
|
||||
if(spell->GetSpellData()->friendly_spell && (caster->IsPlayer() || caster->IsBot()) && (target->IsPlayer() || target->IsBot()) &&
|
||||
((Entity*)target)->GetInfoStruct()->get_engaged_encounter() &&
|
||||
if((spell->GetSpellData()->friendly_spell && caster != target && (caster->IsPlayer() || caster->IsBot()) && (target->IsPlayer() || target->IsBot()) &&
|
||||
((Entity*)target)->GetInfoStruct()->get_engaged_encounter()) &&
|
||||
((!((Entity*)caster)->GetGroupMemberInfo() || !((Entity*)target)->GetGroupMemberInfo()) ||
|
||||
(((Entity*)caster)->GetGroupMemberInfo()->group_id != ((Entity*)target)->GetGroupMemberInfo()->group_id))) {
|
||||
LogWrite(SPELL__DEBUG, 1, "Spell", "%s: Target (%s) is engaged in combat and cannot be assisted.", spell->GetName(), target->GetName());
|
||||
|
|
|
@ -937,7 +937,7 @@ void WorldDatabase::LoadNPCs(ZoneServer* zone){
|
|||
NPC* npc = 0;
|
||||
int32 id = 0;
|
||||
int32 total = 0;
|
||||
MYSQL_RES* result = query.RunQuery2(Q_SELECT,"SELECT npc.spawn_id, s.name, npc.min_level, npc.max_level, npc.enc_level, s.race, s.model_type, npc.class_, npc.gender, s.command_primary, s.command_secondary, s.show_name, npc.min_group_size, npc.max_group_size, npc.hair_type_id, npc.facial_hair_type_id, npc.wing_type_id, npc.chest_type_id, npc.legs_type_id, npc.soga_hair_type_id, npc.soga_facial_hair_type_id, s.attackable, s.show_level, s.targetable, s.show_command_icon, s.display_hand_icon, s.hp, s.power, s.size, s.collision_radius, npc.action_state, s.visual_state, npc.mood_state, npc.initial_state, npc.activity_status, s.faction_id, s.sub_title, s.merchant_id, s.merchant_type, s.size_offset, npc.attack_type, npc.ai_strategy+0, npc.spell_list_id, npc.secondary_spell_list_id, npc.skill_list_id, npc.secondary_skill_list_id, npc.equipment_list_id, npc.str, npc.sta, npc.wis, npc.intel, npc.agi, npc.heat, npc.cold, npc.magic, npc.mental, npc.divine, npc.disease, npc.poison, npc.aggro_radius, npc.cast_percentage, npc.randomize, npc.soga_model_type, npc.heroic_flag, npc.alignment, npc.elemental, npc.arcane, npc.noxious, s.savagery, s.dissonance, npc.hide_hood, npc.emote_state, s.prefix, s.suffix, s.last_name, s.expansion_flag, s.holiday_flag, s.disable_sounds, s.merchant_min_level, s.merchant_max_level, s.aaxp_rewards, npc.water_type, npc.flying_type, s.loot_tier, s.loot_drop_type, npc.scared_by_strong_players\n"
|
||||
MYSQL_RES* result = query.RunQuery2(Q_SELECT,"SELECT npc.spawn_id, s.name, npc.min_level, npc.max_level, npc.enc_level, s.race, s.model_type, npc.class_, npc.gender, s.command_primary, s.command_secondary, s.show_name, npc.min_group_size, npc.max_group_size, npc.hair_type_id, npc.facial_hair_type_id, npc.wing_type_id, npc.chest_type_id, npc.legs_type_id, npc.soga_hair_type_id, npc.soga_facial_hair_type_id, s.attackable, s.show_level, s.targetable, s.show_command_icon, s.display_hand_icon, s.hp, s.power, s.size, s.collision_radius, npc.action_state, s.visual_state, npc.mood_state, npc.initial_state, npc.activity_status, s.faction_id, s.sub_title, s.merchant_id, s.merchant_type, s.size_offset, npc.attack_type, npc.ai_strategy+0, npc.spell_list_id, npc.secondary_spell_list_id, npc.skill_list_id, npc.secondary_skill_list_id, npc.equipment_list_id, npc.str, npc.sta, npc.wis, npc.intel, npc.agi, npc.heat, npc.cold, npc.magic, npc.mental, npc.divine, npc.disease, npc.poison, npc.aggro_radius, npc.cast_percentage, npc.randomize, npc.soga_model_type, npc.heroic_flag, npc.alignment, npc.elemental, npc.arcane, npc.noxious, s.savagery, s.dissonance, npc.hide_hood, npc.emote_state, s.prefix, s.suffix, s.last_name, s.expansion_flag, s.holiday_flag, s.disable_sounds, s.merchant_min_level, s.merchant_max_level, s.aaxp_rewards, npc.water_type, npc.flying_type, s.loot_tier, s.loot_drop_type, npc.scared_by_strong_players, npc.action_state_str\n"
|
||||
"FROM spawn s\n"
|
||||
"INNER JOIN spawn_npcs npc\n"
|
||||
"ON s.id = npc.spawn_id\n"
|
||||
|
@ -1099,6 +1099,11 @@ void WorldDatabase::LoadNPCs(ZoneServer* zone){
|
|||
|
||||
npc->SetScaredByStrongPlayers(atoul(row[85]));
|
||||
|
||||
if(row[86]){
|
||||
std::string action_state_str = std::string(row[86]);
|
||||
npc->GetInfoStruct()->set_action_state(action_state_str);
|
||||
}
|
||||
|
||||
zone->AddNPC(id, npc);
|
||||
total++;
|
||||
LogWrite(NPC__DEBUG, 5, "NPC", "---Loading NPC: '%s' (%u)", npc->appearance.name, id);
|
||||
|
@ -6751,7 +6756,7 @@ bool WorldDatabase::LoadNPC(ZoneServer* zone, int32 spawn_id) {
|
|||
int32 id = 0;
|
||||
DatabaseResult result;
|
||||
|
||||
database_new.Select(&result, "SELECT npc.spawn_id, s.name, npc.min_level, npc.max_level, npc.enc_level, s.race, s.model_type, npc.class_, npc.gender, s.command_primary, s.command_secondary, s.show_name, npc.min_group_size, npc.max_group_size, npc.hair_type_id, npc.facial_hair_type_id, npc.wing_type_id, npc.chest_type_id, npc.legs_type_id, npc.soga_hair_type_id, npc.soga_facial_hair_type_id, s.attackable, s.show_level, s.targetable, s.show_command_icon, s.display_hand_icon, s.hp, s.power, s.size, s.collision_radius, npc.action_state, s.visual_state, npc.mood_state, npc.initial_state, npc.activity_status, s.faction_id, s.sub_title, s.merchant_id, s.merchant_type, s.size_offset, npc.attack_type, npc.ai_strategy+0, npc.spell_list_id, npc.secondary_spell_list_id, npc.skill_list_id, npc.secondary_skill_list_id, npc.equipment_list_id, npc.str, npc.sta, npc.wis, npc.intel, npc.agi, npc.heat, npc.cold, npc.magic, npc.mental, npc.divine, npc.disease, npc.poison, npc.aggro_radius, npc.cast_percentage, npc.randomize, npc.soga_model_type, npc.heroic_flag, npc.alignment, npc.elemental, npc.arcane, npc.noxious, s.savagery, s.dissonance, npc.hide_hood, npc.emote_state, s.prefix, s.suffix, s.last_name, s.disable_sounds, s.merchant_min_level, s.merchant_max_level, s.aaxp_rewards, s.loot_tier, s.loot_drop_type, npc.scared_by_strong_players\n"
|
||||
database_new.Select(&result, "SELECT npc.spawn_id, s.name, npc.min_level, npc.max_level, npc.enc_level, s.race, s.model_type, npc.class_, npc.gender, s.command_primary, s.command_secondary, s.show_name, npc.min_group_size, npc.max_group_size, npc.hair_type_id, npc.facial_hair_type_id, npc.wing_type_id, npc.chest_type_id, npc.legs_type_id, npc.soga_hair_type_id, npc.soga_facial_hair_type_id, s.attackable, s.show_level, s.targetable, s.show_command_icon, s.display_hand_icon, s.hp, s.power, s.size, s.collision_radius, npc.action_state, s.visual_state, npc.mood_state, npc.initial_state, npc.activity_status, s.faction_id, s.sub_title, s.merchant_id, s.merchant_type, s.size_offset, npc.attack_type, npc.ai_strategy+0, npc.spell_list_id, npc.secondary_spell_list_id, npc.skill_list_id, npc.secondary_skill_list_id, npc.equipment_list_id, npc.str, npc.sta, npc.wis, npc.intel, npc.agi, npc.heat, npc.cold, npc.magic, npc.mental, npc.divine, npc.disease, npc.poison, npc.aggro_radius, npc.cast_percentage, npc.randomize, npc.soga_model_type, npc.heroic_flag, npc.alignment, npc.elemental, npc.arcane, npc.noxious, s.savagery, s.dissonance, npc.hide_hood, npc.emote_state, s.prefix, s.suffix, s.last_name, s.disable_sounds, s.merchant_min_level, s.merchant_max_level, s.aaxp_rewards, s.loot_tier, s.loot_drop_type, npc.scared_by_strong_players, npc.action_state_str\n"
|
||||
"FROM spawn s\n"
|
||||
"INNER JOIN spawn_npcs npc\n"
|
||||
"ON npc.spawn_id = s.id\n"
|
||||
|
@ -6889,6 +6894,11 @@ bool WorldDatabase::LoadNPC(ZoneServer* zone, int32 spawn_id) {
|
|||
|
||||
npc->SetScaredByStrongPlayers(result.GetInt32(81));
|
||||
|
||||
if(!result.IsNull(82)){
|
||||
std::string action_state_str = std::string(result.GetString(82));
|
||||
npc->GetInfoStruct()->set_action_state(action_state_str);
|
||||
}
|
||||
|
||||
zone->AddNPC(id, npc);
|
||||
|
||||
//skipped spells/skills/equipment as it is all loaded, the following rely on a spawn to load
|
||||
|
|
|
@ -537,9 +537,11 @@
|
|||
<Data ElementName="soga_hair_color1" Type="EQ2_Color" /> <!-- 648 -->
|
||||
<Data ElementName="soga_hair_color2" Type="EQ2_Color" /> <!-- 651 -->
|
||||
<Data ElementName="soga_hair_highlight" Type="EQ2_Color" /> <!-- 654 -->
|
||||
<Data ElementName="unknown" Type="int8" Size="6" /> <!-- 657 -->
|
||||
<Data ElementName="combat_voice" Type="int16" Size="1" />
|
||||
<Data ElementName="emote_voice" Type="int16" Size="1" />
|
||||
<Data ElementName="unknown" Type="int8" Size="2" /> <!-- 657 -->
|
||||
<Data ElementName="flags" Type="int8" Size="1" /><!-- 663 1 == invisible, 2 == show_hood, 8 == crouch -->
|
||||
<Data ElementName="unknown" Type="int8" Size="3" /> <!-- 664 -->
|
||||
<Data ElementName="unknown2" Type="int8" Size="3" /> <!-- 664 -->
|
||||
<Data ElementName="temporary_scale" Type="float" Size="1" /> <!-- 667 -->
|
||||
<Data ElementName="name" Type="char" Size="64" /> <!-- 671 -->
|
||||
<Data ElementName="last_name" Type="char" Size="64" /> <!-- 735 -->
|
||||
|
|
|
@ -9351,6 +9351,7 @@ to zero and treated like placeholders." />
|
|||
<Data ElementName="status2" Type="int32" Size="1" />
|
||||
</Data>
|
||||
<Data ElementName="type" Type="int8" /> <!-- 0==buy, 1==sell, 16==repair, 128==goblin game -->
|
||||
<Data ElementName="unknown" Type="int8" Size="2" />
|
||||
</Struct>
|
||||
<Struct Name="WS_UpdateMerchant" ClientVersion="547" OpcodeName="OP_ClientCmdMsg" OpcodeType="OP_EqUpdateMerchantCmd">
|
||||
<Data ElementName="spawn_id" Type="int32" />
|
||||
|
|
Loading…
Reference in a new issue