Activated load/save of new bot data fields; added command '#bot clearfollowdistance'

This commit is contained in:
Uleat 2015-10-16 18:09:22 -04:00
parent efeb80cc8b
commit 85adea631d
4 changed files with 128 additions and 51 deletions

View File

@ -1,5 +1,8 @@
EQEMu Changelog (Started on Sept 24, 2003 15:50) EQEMu Changelog (Started on Sept 24, 2003 15:50)
------------------------------------------------------- -------------------------------------------------------
== 10/16/2015 ==
Uleat: Added command '#bot clearfollowdistance [ <target> | spawned | all ]' to coincide with the activation of the load/save feature for follow_distance
== 10/13/2015 == == 10/13/2015 ==
Uleat: Important update to 2015_09_30_bots.sql - fix for orphaned entries causing crashes during the conversion process Uleat: Important update to 2015_09_30_bots.sql - fix for orphaned entries causing crashes during the conversion process
Note: Please visit the thread below if you encounter issues during the conversion process Note: Please visit the thread below if you encounter issues during the conversion process

View File

@ -155,8 +155,8 @@ BEGIN
`poison` SMALLINT(5) NOT NULL DEFAULT '0', `poison` SMALLINT(5) NOT NULL DEFAULT '0',
`disease` SMALLINT(5) NOT NULL DEFAULT '0', `disease` SMALLINT(5) NOT NULL DEFAULT '0',
`corruption` SMALLINT(5) NOT NULL DEFAULT '0', `corruption` SMALLINT(5) NOT NULL DEFAULT '0',
`show_helm` INT(11) UNSIGNED NOT NULL DEFAULT '0', -- Unused `show_helm` INT(11) UNSIGNED NOT NULL DEFAULT '0',
`follow_distance` INT(11) UNSIGNED NOT NULL DEFAULT '200', -- Unused `follow_distance` INT(11) UNSIGNED NOT NULL DEFAULT '200',
PRIMARY KEY (`bot_id`) PRIMARY KEY (`bot_id`)
) ENGINE=InnoDB; ) ENGINE=InnoDB;
CREATE TABLE `bot_inspect_messages` ( CREATE TABLE `bot_inspect_messages` (

View File

@ -66,7 +66,7 @@ Bot::Bot(NPCType npcTypeData, Client* botOwner) : NPC(&npcTypeData, nullptr, glm
SetShowHelm(true); SetShowHelm(true);
CalcChanceToCast(); CalcChanceToCast();
rest_timer.Disable(); rest_timer.Disable();
SetFollowDistance(184); SetFollowDistance(BOT_DEFAULT_FOLLOW_DISTANCE);
// Do this once and only in this constructor // Do this once and only in this constructor
GenerateAppearance(); GenerateAppearance();
GenerateBaseStats(); GenerateBaseStats();
@ -144,7 +144,7 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to
SetNumHealRotationMembers(0); SetNumHealRotationMembers(0);
CalcChanceToCast(); CalcChanceToCast();
rest_timer.Disable(); rest_timer.Disable();
SetFollowDistance(184); SetFollowDistance(BOT_DEFAULT_FOLLOW_DISTANCE);
strcpy(this->name, this->GetCleanName()); strcpy(this->name, this->GetCleanName());
database.GetBotInspectMessage(this->GetBotID(), &_botInspectMessage); database.GetBotInspectMessage(this->GetBotID(), &_botInspectMessage);
LoadGuildMembership(&_guildId, &_guildRank, &_guildName); LoadGuildMembership(&_guildId, &_guildRank, &_guildName);
@ -1593,7 +1593,9 @@ bool Bot::Save()
" `magic`," " `magic`,"
" `poison`," " `poison`,"
" `disease`," " `disease`,"
" `corruption`" " `corruption`,"
" `show_helm`,"
" `follow_distance`"
")" ")"
" VALUES (" " VALUES ("
"'%u'," /*owner_id*/ "'%u'," /*owner_id*/
@ -1635,7 +1637,9 @@ bool Bot::Save()
" '%i'," /*magic*/ " '%i'," /*magic*/
" '%i'," /*poison*/ " '%i'," /*poison*/
" '%i'," /*disease*/ " '%i'," /*disease*/
" '%i'" /*corruption*/ " '%i'," /*corruption*/
" '1'," /*show_helm*/
" '%i'" /*follow_distance*/
")", ")",
this->_botOwnerCharacterID, this->_botOwnerCharacterID,
this->GetBotSpellID(), this->GetBotSpellID(),
@ -1673,7 +1677,8 @@ bool Bot::Save()
GetMR(), GetMR(),
GetPR(), GetPR(),
GetDR(), GetDR(),
GetCorrup() GetCorrup(),
BOT_DEFAULT_FOLLOW_DISTANCE
); );
auto results = database.QueryDatabase(query); auto results = database.QueryDatabase(query);
if(!results.Success()) { if(!results.Success()) {
@ -1734,7 +1739,9 @@ bool Bot::Save()
" `magic` = '%i'," " `magic` = '%i',"
" `poison` = '%i'," " `poison` = '%i',"
" `disease` = '%i'," " `disease` = '%i',"
" `corruption` = '%i'" " `corruption` = '%i',"
" `show_helm` = '%i',"
" `follow_distance` = '%i'"
" WHERE `bot_id` = '%u'", " WHERE `bot_id` = '%u'",
_botOwnerCharacterID, _botOwnerCharacterID,
this->GetBotSpellID(), this->GetBotSpellID(),
@ -1774,6 +1781,8 @@ bool Bot::Save()
_basePR, _basePR,
_baseDR, _baseDR,
_baseCorrup, _baseCorrup,
(GetShowHelm() ? 1 : 0),
GetFollowDistance(),
GetBotID() GetBotID()
); );
auto results = database.QueryDatabase(query); auto results = database.QueryDatabase(query);
@ -3626,13 +3635,13 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) {
ns->spawn.is_npc = 0; // 0=no, 1=yes ns->spawn.is_npc = 0; // 0=no, 1=yes
ns->spawn.is_pet = 0; ns->spawn.is_pet = 0;
ns->spawn.guildrank = 0; ns->spawn.guildrank = 0;
ns->spawn.showhelm = GetShowHelm(); ns->spawn.showhelm = GetShowHelm() ? 1 : 0;
ns->spawn.flymode = 0; ns->spawn.flymode = 0;
ns->spawn.size = 0; ns->spawn.size = 0;
ns->spawn.NPC = 0; // 0=player,1=npc,2=pc corpse,3=npc corpse ns->spawn.NPC = 0; // 0=player,1=npc,2=pc corpse,3=npc corpse
UpdateActiveLight(); UpdateActiveLight();
ns->spawn.light = m_Light.Type.Active; ns->spawn.light = m_Light.Type.Active;
ns->spawn.helm = (GetShowHelm() ? helmtexture : 0); //0xFF; ns->spawn.helm = helmtexture; //(GetShowHelm() ? helmtexture : 0); //0xFF;
ns->spawn.equip_chest2 = texture; //0xFF; ns->spawn.equip_chest2 = texture; //0xFF;
const Item_Struct* item = 0; const Item_Struct* item = 0;
const ItemInst* inst = 0; const ItemInst* inst = 0;
@ -3696,7 +3705,6 @@ uint32 Bot::GetBotIDByBotName(std::string botName) {
Bot* Bot::LoadBot(uint32 botID, std::string* errorMessage) Bot* Bot::LoadBot(uint32 botID, std::string* errorMessage)
{ {
Bot* loadedBot = nullptr;
if(botID == 0) if(botID == 0)
return nullptr; return nullptr;
@ -3706,46 +3714,52 @@ Bot* Bot::LoadBot(uint32 botID, std::string* errorMessage)
" `spells_id`," " `spells_id`,"
" `name`," " `name`,"
" `last_name`," " `last_name`,"
" `level`," " `title`," /*planned use[4]*/
" `suffix`," /*planned use[5]*/
" `zone_id`,"
" `gender`,"
" `race`," " `race`,"
" `class`," " `class`,"
" `gender`," " `level`,"
" `deity`," /*planned use[11]*/
" `creation_day`," /*not in-use[12]*/
" `last_spawn`," /*not in-use[13]*/
" `time_spawned`,"
" `size`," " `size`,"
" `face`," " `face`,"
" `hair_style`,"
" `hair_color`," " `hair_color`,"
" `hair_style`,"
" `beard`,"
" `beard_color`,"
" `eye_color_1`," " `eye_color_1`,"
" `eye_color_2`," " `eye_color_2`,"
" `beard_color`,"
" `beard`,"
" `drakkin_heritage`," " `drakkin_heritage`,"
" `drakkin_tattoo`," " `drakkin_tattoo`,"
" `drakkin_details`," " `drakkin_details`,"
" `hp`," " `ac`," /*not in-use[26]*/
" `mana`,"
" `magic`,"
" `cold`,"
" `disease`,"
" `fire`,"
" `poison`,"
" `corruption`,"
" `ac`,"
" `str`,"
" `sta`,"
" `dex`,"
" `agi`,"
" `int`,"
" `wis`,"
" `cha`,"
" `atk`," " `atk`,"
" `creation_day`," " `hp`,"
" `last_spawn`," " `mana`," /*not in-use[29]*/
" `time_spawned`," " `str`," /*not in-use[30]*/
" `zone_id`" " `sta`," /*not in-use[31]*/
" `cha`," /*not in-use[32]*/
" `dex`," /*not in-use[33]*/
" `int`," /*not in-use[34]*/
" `agi`," /*not in-use[35]*/
" `wis`," /*not in-use[36]*/
" `fire`," /*not in-use[37]*/
" `cold`," /*not in-use[38]*/
" `magic`," /*not in-use[39]*/
" `poison`," /*not in-use[40]*/
" `disease`," /*not in-use[41]*/
" `corruption`," /*not in-use[42]*/
" `show_helm`,"
" `follow_distance`"
" FROM `bot_data`" " FROM `bot_data`"
" WHERE `bot_id` = '%u'", " WHERE `bot_id` = '%u'",
botID botID
); );
auto results = database.QueryDatabase(query); auto results = database.QueryDatabase(query);
if(!results.Success()) { if(!results.Success()) {
*errorMessage = std::string(results.ErrorMessage()); *errorMessage = std::string(results.ErrorMessage());
@ -3755,29 +3769,30 @@ Bot* Bot::LoadBot(uint32 botID, std::string* errorMessage)
if (results.RowCount() == 0) if (results.RowCount() == 0)
return nullptr; return nullptr;
// TODO: Consider removing resists and basic attributes from the load query above since we're using defaultNPCType values instead
auto row = results.begin(); auto row = results.begin();
NPCType defaultNPCTypeStruct = CreateDefaultNPCTypeStructForBot(std::string(row[2]), std::string(row[3]), atoi(row[4]), atoi(row[5]), atoi(row[6]), atoi(row[7])); NPCType defaultNPCTypeStruct = CreateDefaultNPCTypeStructForBot(std::string(row[2]), std::string(row[3]), atoi(row[10]), atoi(row[8]), atoi(row[9]), atoi(row[7]));
NPCType tempNPCStruct = FillNPCTypeStruct( NPCType tempNPCStruct = FillNPCTypeStruct(
atoi(row[1]), atoi(row[1]),
std::string(row[2]), std::string(row[2]),
std::string(row[3]), std::string(row[3]),
atoi(row[4]),
atoi(row[5]),
atoi(row[6]),
atoi(row[7]),
atof(row[8]),
atoi(row[9]),
atoi(row[10]), atoi(row[10]),
atoi(row[11]), atoi(row[8]),
atoi(row[12]), atoi(row[9]),
atoi(row[13]), atoi(row[7]),
atoi(row[14]), atof(row[15]),
atoi(row[15]),
atoi(row[16]), atoi(row[16]),
atoi(row[17]),
atoi(row[18]), atoi(row[18]),
atoi(row[19]), atoi(row[17]),
atoi(row[21]),
atoi(row[22]),
atoi(row[20]), atoi(row[20]),
atoi(row[19]),
atoi(row[23]),
atoi(row[24]),
atoi(row[25]),
atoi(row[27]),
atoi(row[28]),
defaultNPCTypeStruct.MR, defaultNPCTypeStruct.MR,
defaultNPCTypeStruct.CR, defaultNPCTypeStruct.CR,
defaultNPCTypeStruct.DR, defaultNPCTypeStruct.DR,
@ -3794,7 +3809,13 @@ Bot* Bot::LoadBot(uint32 botID, std::string* errorMessage)
defaultNPCTypeStruct.CHA, defaultNPCTypeStruct.CHA,
defaultNPCTypeStruct.ATK defaultNPCTypeStruct.ATK
); );
loadedBot = new Bot(botID, atoi(row[0]), atoi(row[1]), atof(row[38]), atoi(row[39]), tempNPCStruct);
Bot* loadedBot = new Bot(botID, atoi(row[0]), atoi(row[1]), atof(row[14]), atoi(row[6]), tempNPCStruct);
if (loadedBot) {
loadedBot->SetShowHelm((atoi(row[43]) > 0 ? true : false));
loadedBot->SetFollowDistance(atoi(row[44]));
}
return loadedBot; return loadedBot;
} }
@ -9244,6 +9265,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) {
c->Message(0, "#bot botgroup help - Displays the commands available to manage bot ONLY groups."); c->Message(0, "#bot botgroup help - Displays the commands available to manage bot ONLY groups.");
c->Message(0, "#bot mana [<bot name or target> | all] - Displays a mana report for all your spawned bots."); c->Message(0, "#bot mana [<bot name or target> | all] - Displays a mana report for all your spawned bots.");
c->Message(0, "#bot setfollowdistance ### - sets target bots follow distance to ### (ie 30 or 250)."); c->Message(0, "#bot setfollowdistance ### - sets target bots follow distance to ### (ie 30 or 250).");
c->Message(0, "#bot clearfollowdistance [<target> | spawned | all] - clears user-defined follow distance setting for bot target, spawned or all - includes spawned and unspawned.");
c->Message(0, "#bot [hair|haircolor|beard|beardcolor|face|eyes|heritage|tattoo|details <value>] - Change your bot's appearance."); c->Message(0, "#bot [hair|haircolor|beard|beardcolor|face|eyes|heritage|tattoo|details <value>] - Change your bot's appearance.");
c->Message(0, "#bot armorcolor <slot> <red> <green> <blue> - #bot help armorcolor for info"); c->Message(0, "#bot armorcolor <slot> <red> <green> <blue> - #bot help armorcolor for info");
c->Message(0, "#bot taunt [on|off] - Determines whether or not your targeted bot will taunt."); c->Message(0, "#bot taunt [on|off] - Determines whether or not your targeted bot will taunt.");
@ -9300,6 +9322,43 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) {
return; return;
} }
if (!strcasecmp(sep->arg[1], "clearfollowdistance")) {
bool case_all = !strcasecmp(sep->arg[2], "all");
bool case_spawned = !strcasecmp(sep->arg[2], "spawned");
if (case_all || case_spawned) {
if (case_all) {
std::string query = StringFormat(
"UPDATE `bot_data`"
" SET `follow_distance` = '%u'"
" WHERE `owner_id` = '%u'",
BOT_DEFAULT_FOLLOW_DISTANCE,
c->CharacterID()
);
auto results = database.QueryDatabase(query);
if (!results.Success())
return;
}
std::list<Bot*> spawnedBots = entity_list.GetBotsByBotOwnerCharacterID(c->CharacterID());
if (!spawnedBots.empty()) {
for (std::list<Bot*>::iterator botsListItr = spawnedBots.begin(); botsListItr != spawnedBots.end(); ++botsListItr) {
Bot* tempBot = *botsListItr;
if (tempBot) {
tempBot->SetFollowDistance(BOT_DEFAULT_FOLLOW_DISTANCE);
}
}
}
}
else if ((c->GetTarget() == nullptr) || (c->GetTarget() == c) || (!c->GetTarget()->IsBot()) || (c->GetTarget()->CastToBot()->GetBotOwner() != c)) {
c->Message(15, "You must target a bot you own!");
}
else {
c->GetTarget()->SetFollowDistance(BOT_DEFAULT_FOLLOW_DISTANCE);
}
return;
}
//bot armor colors //bot armor colors
if(!strcasecmp(sep->arg[1], "armorcolor")) { if(!strcasecmp(sep->arg[1], "armorcolor")) {
if(c->GetTarget() && c->GetTarget()->IsBot() && (c->GetTarget()->CastToBot()->GetBotOwner() == c)) { if(c->GetTarget() && c->GetTarget()->IsBot() && (c->GetTarget()->CastToBot()->GetBotOwner() == c)) {
@ -12713,6 +12772,19 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) {
Bot* b = target->CastToBot(); Bot* b = target->CastToBot();
if (b) { if (b) {
b->SetShowHelm(showhelm); b->SetShowHelm(showhelm);
EQApplicationPacket* outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct));
SpawnAppearance_Struct* sa_out = (SpawnAppearance_Struct*)outapp->pBuffer;
/*
[10-16-2015 :: 14:58:02] [Packet :: Client -> Server (Dump)] [OP_SpawnAppearance - 0x01d1] [Size: 10]
0: A4 02 [2B 00] 00 00 00 00 - showhelm = false
[10-16-2015 :: 14:57:56] [Packet :: Client -> Server (Dump)] [OP_SpawnAppearance - 0x01d1] [Size: 10]
0: A4 02 [2B 00] 01 00 00 00 - showhelm = true
*/
sa_out->spawn_id = b->GetID();
sa_out->type = AT_ShowHelm; // value = 43 (0x002B)
sa_out->parameter = (showhelm ? 1 : 0);
entity_list.QueueClients(b, outapp, true);
safe_delete(outapp);
c->Message(0, "Your bot will %s show their helmet.", (showhelm ? "now" : "no longer")); c->Message(0, "Your bot will %s show their helmet.", (showhelm ? "now" : "no longer"));
} }
} }

View File

@ -18,6 +18,8 @@
#include <sstream> #include <sstream>
#define BOT_DEFAULT_FOLLOW_DISTANCE 184
extern WorldServer worldserver; extern WorldServer worldserver;
const int BotAISpellRange = 100; // TODO: Write a method that calcs what the bot's spell range is based on spell, equipment, AA, whatever and replace this const int BotAISpellRange = 100; // TODO: Write a method that calcs what the bot's spell range is based on spell, equipment, AA, whatever and replace this