[Quest API] Expand Bot quest API functionality. (#2096)

* [Quest API] Expand Bot quest API functionality.
- Add $bot->AddItem(slot_id, item_id, charges, attuned, augment_one, augment_two, augment_three, augment_four, augment_five, augment_six) to Perl.
- Add $bot->CountItem(item_id) to Perl.
- Add $bot->HasItem(item_id) to Perl.
- Add $bot->RemoveItem(item_id) to Perl.
- Add bot:AddItem(slot_id, item_id, charges, attuned, augment_one, augment_two, augment_three, augment_four, augment_five, augment_six) to Lua.
- Add bot:CountItem(item_id) to Lua.
- Add bot:GetOwner() to Lua.
- Add bot:HasItem(item_id) to Lua.
- Add bot:RemoveItem(item_id) to Lua.

* Fix possible crash.
This commit is contained in:
Kinglykrab 2022-05-03 23:04:54 -04:00 committed by GitHub
parent 837c0a4385
commit b2b87ea4e0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 1234 additions and 753 deletions

View File

@ -3791,7 +3791,12 @@ void Bot::Depop() {
}
bool Bot::Spawn(Client* botCharacterOwner) {
if(GetBotID() > 0 && _botOwnerCharacterID > 0 && botCharacterOwner && botCharacterOwner->CharacterID() == _botOwnerCharacterID) {
if (
GetBotID() &&
_botOwnerCharacterID &&
botCharacterOwner &&
botCharacterOwner->CharacterID() == _botOwnerCharacterID
) {
// Rename the bot name to make sure that Mob::GetName() matches Mob::GetCleanName() so we dont have a bot named "Jesuschrist001"
strcpy(name, GetCleanName());
@ -3802,10 +3807,23 @@ bool Bot::Spawn(Client* botCharacterOwner) {
helmtexture = 0; //0xFF;
texture = 0; //0xFF;
if(Save())
GetBotOwner()->CastToClient()->Message(Chat::White, "%s saved.", GetCleanName());
else
GetBotOwner()->CastToClient()->Message(Chat::Red, "%s save failed!", GetCleanName());
if (Save()) {
GetBotOwner()->CastToClient()->Message(
Chat::White,
fmt::format(
"{} saved.",
GetCleanName()
).c_str()
);
} else {
GetBotOwner()->CastToClient()->Message(
Chat::Red,
fmt::format(
"{} save failed!",
GetCleanName()
).c_str()
);
}
// Spawn the bot at the bot owner's loc
m_Position.x = botCharacterOwner->GetX();
@ -3825,14 +3843,15 @@ bool Bot::Spawn(Client* botCharacterOwner) {
ping_timer.Start(8000);
// there is something askew with spawn struct appearance fields...
// I re-enabled this until I can sort it out
uint32 itemID = 0;
uint8 materialFromSlot = 0xFF;
for (int i = EQ::invslot::EQUIPMENT_BEGIN; i <= EQ::invslot::EQUIPMENT_END; ++i) {
itemID = GetBotItemBySlot(i);
if(itemID != 0) {
materialFromSlot = EQ::InventoryProfile::CalcMaterialFromSlot(i);
if(materialFromSlot != 0xFF)
SendWearChange(materialFromSlot);
uint32 item_id = 0;
uint8 material_from_slot = 0xFF;
for (int slot_id = EQ::invslot::EQUIPMENT_BEGIN; slot_id <= EQ::invslot::EQUIPMENT_END; ++slot_id) {
item_id = GetBotItemBySlot(slot_id);
if (item_id != 0) {
material_from_slot = EQ::InventoryProfile::CalcMaterialFromSlot(slot_id);
if (material_from_slot != 0xFF) {
SendWearChange(material_from_slot);
}
}
}
@ -3843,26 +3862,29 @@ bool Bot::Spawn(Client* botCharacterOwner) {
}
// Deletes the inventory record for the specified item from the database for this bot.
void Bot::RemoveBotItemBySlot(uint32 slotID, std::string *errorMessage)
void Bot::RemoveBotItemBySlot(uint16 slot_id, std::string *error_message)
{
if(!GetBotID())
if (!GetBotID()) {
return;
}
if(!database.botdb.DeleteItemBySlot(GetBotID(), slotID))
*errorMessage = BotDatabase::fail::DeleteItemBySlot();
if (!database.botdb.DeleteItemBySlot(GetBotID(), slot_id)) {
*error_message = BotDatabase::fail::DeleteItemBySlot();
}
m_inv.DeleteItem(slotID);
m_inv.DeleteItem(slot_id);
UpdateEquipmentLight();
}
// Retrieves all the inventory records from the database for this bot.
void Bot::GetBotItems(EQ::InventoryProfile &inv, std::string* errorMessage)
void Bot::GetBotItems(EQ::InventoryProfile &inv, std::string* error_message)
{
if(!GetBotID())
if (!GetBotID()) {
return;
}
if (!database.botdb.LoadItems(GetBotID(), inv)) {
*errorMessage = BotDatabase::fail::LoadItems();
*error_message = BotDatabase::fail::LoadItems();
return;
}
@ -3870,15 +3892,23 @@ void Bot::GetBotItems(EQ::InventoryProfile &inv, std::string* errorMessage)
}
// Returns the inventory record for this bot from the database for the specified equipment slot.
uint32 Bot::GetBotItemBySlot(uint32 slotID)
uint32 Bot::GetBotItemBySlot(uint16 slot_id)
{
uint32 item_id = 0;
if(!GetBotID())
if (!GetBotID()) {
return item_id;
}
if (!database.botdb.LoadItemBySlot(GetBotID(), slotID, item_id)) {
if (GetBotOwner() && GetBotOwner()->IsClient())
GetBotOwner()->CastToClient()->Message(Chat::Red, "%s", BotDatabase::fail::LoadItemBySlot());
if (!database.botdb.LoadItemBySlot(GetBotID(), slot_id, item_id)) {
if (GetBotOwner() && GetBotOwner()->IsClient()) {
GetBotOwner()->CastToClient()->Message(
Chat::Red,
fmt::format(
"{}",
BotDatabase::fail::LoadItemBySlot()
).c_str()
);
}
}
return item_id;
@ -4075,63 +4105,191 @@ void Bot::SendBotArcheryWearChange(uint8 material_slot, uint32 material, uint32
}
// Returns the item id that is in the bot inventory collection for the specified slot.
EQ::ItemInstance* Bot::GetBotItem(uint32 slotID) {
EQ::ItemInstance* item = m_inv.GetItem(slotID);
if(item)
EQ::ItemInstance* Bot::GetBotItem(uint16 slot_id) {
EQ::ItemInstance* item = m_inv.GetItem(slot_id);
if (item) {
return item;
}
return nullptr;
}
// Adds the specified item it bot to the NPC equipment array and to the bot inventory collection.
void Bot::BotAddEquipItem(int slot, uint32 id) {
void Bot::BotAddEquipItem(uint16 slot_id, uint32 item_id) {
// this is being called before bot is assigned an entity id..
// ..causing packets to be sent out to zone with an id of '0'
if(slot > 0 && id > 0) {
uint8 materialFromSlot = EQ::InventoryProfile::CalcMaterialFromSlot(slot);
if (item_id) {
uint8 material_from_slot = EQ::InventoryProfile::CalcMaterialFromSlot(slot_id);
if (materialFromSlot != EQ::textures::materialInvalid) {
equipment[slot] = id; // npc has more than just material slots. Valid material should mean valid inventory index
if (GetID()) // temp hack fix
SendWearChange(materialFromSlot);
if (material_from_slot != EQ::textures::materialInvalid) {
equipment[slot_id] = item_id; // npc has more than just material slots. Valid material should mean valid inventory index
if (GetID()) { // temp hack fix
SendWearChange(material_from_slot);
}
}
UpdateEquipmentLight();
if (UpdateActiveLight())
if (GetID()) // temp hack fix
if (UpdateActiveLight()) {
if (GetID()) { // temp hack fix
SendAppearancePacket(AT_Light, GetActiveLightType());
}
}
}
}
// Erases the specified item from bot the NPC equipment array and from the bot inventory collection.
void Bot::BotRemoveEquipItem(int16 slot)
void Bot::BotRemoveEquipItem(uint16 slot_id)
{
uint8 material_slot = EQ::InventoryProfile::CalcMaterialFromSlot(slot);
uint8 material_slot = EQ::InventoryProfile::CalcMaterialFromSlot(slot_id);
if (material_slot != EQ::textures::materialInvalid) {
equipment[slot] = 0; // npc has more than just material slots. Valid material should mean valid inventory index
equipment[slot_id] = 0; // npc has more than just material slots. Valid material should mean valid inventory index
SendWearChange(material_slot);
if (material_slot == EQ::textures::armorChest)
if (material_slot == EQ::textures::armorChest) {
SendWearChange(EQ::textures::armorArms);
}
}
UpdateEquipmentLight();
if (UpdateActiveLight())
if (UpdateActiveLight()) {
SendAppearancePacket(AT_Light, GetActiveLightType());
}
}
void Bot::BotTradeAddItem(uint32 id, const EQ::ItemInstance* inst, int16 charges, uint32 equipableSlots, uint16 lootSlot, std::string* errorMessage, bool addToDb)
void Bot::BotTradeAddItem(const EQ::ItemInstance* inst, uint16 slot_id, std::string* error_message, bool save_to_database)
{
if(addToDb) {
if (!database.botdb.SaveItemBySlot(this, lootSlot, inst)) {
*errorMessage = BotDatabase::fail::SaveItemBySlot();
if (save_to_database) {
if (!database.botdb.SaveItemBySlot(this, slot_id, inst)) {
*error_message = BotDatabase::fail::SaveItemBySlot();
return;
}
m_inv.PutItem(lootSlot, *inst);
m_inv.PutItem(slot_id, *inst);
}
BotAddEquipItem(lootSlot, id);
auto item_id = inst ? inst->GetID() : 0;
BotAddEquipItem(slot_id, item_id);
}
void Bot::AddItem(
uint16 slot_id,
uint32 item_id,
int16 charges,
bool attuned,
uint32 augment_one,
uint32 augment_two,
uint32 augment_three,
uint32 augment_four,
uint32 augment_five,
uint32 augment_six
) {
auto inst = database.CreateItem(
item_id,
charges,
augment_one,
augment_two,
augment_three,
augment_four,
augment_five,
augment_six,
attuned
);
if (!inst) {
LogError(
"Bot:AddItem Invalid Item data: ID [{}] Charges [{}] Aug1 [{}] Aug2 [{}] Aug3 [{}] Aug4 [{}] Aug5 [{}] Aug6 [{}] Attuned [{}]",
item_id,
charges,
augment_one,
augment_two,
augment_three,
augment_four,
augment_five,
augment_six,
attuned
);
return;
}
if (!database.botdb.SaveItemBySlot(this, slot_id, inst)) {
LogError("Failed to save item by slot to slot [{}] for [{}].", slot_id, GetCleanName());
return;
}
m_inv.PutItem(slot_id, *inst);
BotAddEquipItem(slot_id, item_id);
}
uint32 Bot::CountItem(uint32 item_id) {
uint32 item_count = 0;
EQ::ItemInstance *inst = nullptr;
for (uint16 slot_id = EQ::invslot::EQUIPMENT_BEGIN; slot_id <= EQ::invslot::EQUIPMENT_END; ++slot_id) {
inst = GetBotItem(slot_id);
if (!inst || !inst->GetItem()) {
continue;
}
if (inst->GetID() == item_id) {
item_count++;
}
}
return item_count;
}
bool Bot::HasItem(uint32 item_id) {
bool has_item = false;
EQ::ItemInstance *inst = nullptr;
for (uint16 slot_id = EQ::invslot::EQUIPMENT_BEGIN; slot_id <= EQ::invslot::EQUIPMENT_END; ++slot_id) {
inst = GetBotItem(slot_id);
if (!inst || !inst->GetItem()) {
continue;
}
if (inst->GetID() == item_id) {
has_item = true;
break;
}
}
return has_item;
}
void Bot::RemoveItem(uint32 item_id) {
EQ::ItemInstance *inst = nullptr;
for (uint16 slot_id = EQ::invslot::EQUIPMENT_BEGIN; slot_id <= EQ::invslot::EQUIPMENT_END; ++slot_id) {
inst = GetBotItem(slot_id);
if (!inst || !inst->GetItem()) {
continue;
}
if (inst->GetID() == item_id) {
std::string error_message;
RemoveBotItemBySlot(slot_id, &error_message);
if (!error_message.empty()) {
if (GetOwner()) {
GetOwner()->CastToClient()->Message(
Chat::Magenta,
fmt::format(
"Database Error: {}",
error_message
).c_str()
);
}
return;
}
BotRemoveEquipItem(slot_id);
CalcBotStats(GetOwner()->CastToClient()->GetBotOption(Client::booStatsUpdate));
return;
}
}
}
bool Bot::RemoveBotFromGroup(Bot* bot, Group* group) {
@ -4181,21 +4339,28 @@ bool Bot::AddBotToGroup(Bot* bot, Group* group) {
}
// Completes a trade with a client bot owner
void Bot::FinishTrade(Client* client, BotTradeType tradeType)
void Bot::FinishTrade(Client* client, BotTradeType trade_type)
{
if (!client || (GetOwner() != client) || client->GetTradeskillObject() || client->trade->state == Trading) {
if (client)
if (
!client ||
GetOwner() != client ||
client->GetTradeskillObject() ||
client->trade->state == Trading
) {
if (client) {
client->ResetTrade();
}
return;
}
// these notes are not correct or obselete
if (tradeType == BotTradeClientNormal) {
if (trade_type == BotTradeClientNormal) {
// Items being traded are found in the normal trade window used to trade between a Client and a Client or NPC
// Items in this mode are found in slot ids 3000 thru 3003 - thought bots used the full 8-slot window..?
PerformTradeWithClient(EQ::invslot::TRADE_BEGIN, EQ::invslot::TRADE_END, client); // {3000..3007}
}
else if (tradeType == BotTradeClientNoDropNoTrade) {
else if (trade_type == BotTradeClientNoDropNoTrade) {
// Items being traded are found on the Client's cursor slot, slot id 30. This item can be either a single item or it can be a bag.
// If it is a bag, then we have to search for items in slots 331 thru 340
PerformTradeWithClient(EQ::invslot::slotCursor, EQ::invslot::slotCursor, client);
@ -4314,7 +4479,7 @@ void Bot::PerformTradeWithClient(int16 begin_slot_id, int16 end_slot_id, Client*
return;
}
if (trade_instance->IsStackable() && (trade_instance->GetCharges() < trade_instance->GetItem()->StackSize)) { // temp until partial stacks are implemented
if (trade_instance->IsStackable() && trade_instance->GetCharges() < trade_instance->GetItem()->StackSize) { // temp until partial stacks are implemented
client->Message(
Chat::Yellow,
fmt::format(
@ -4586,7 +4751,7 @@ void Bot::PerformTradeWithClient(int16 begin_slot_id, int16 end_slot_id, Client*
if (return_iterator.from_bot_slot == invslot::slotCursor) { // failed trade return
// no movement action required
} else if ((return_iterator.from_bot_slot >= invslot::TRADE_BEGIN) && (return_iterator.from_bot_slot <= invslot::TRADE_END)) { // failed trade returns
} else if (return_iterator.from_bot_slot >= invslot::TRADE_BEGIN && return_iterator.from_bot_slot <= invslot::TRADE_END) { // failed trade returns
client->PutItemInInventory(return_iterator.to_client_slot, *return_iterator.return_item_instance);
client->SendItemPacket(return_iterator.to_client_slot, return_iterator.return_item_instance, ItemPacketTrade);
client->DeleteItemInInventory(return_iterator.from_bot_slot);
@ -6548,17 +6713,18 @@ bool Bot::IsBotAttackAllowed(Mob* attacker, Mob* target, bool& hasRuleDefined) {
return Result;
}
void Bot::EquipBot(std::string* errorMessage) {
GetBotItems(m_inv, errorMessage);
void Bot::EquipBot(std::string* error_message) {
GetBotItems(m_inv, error_message);
const EQ::ItemInstance* inst = nullptr;
const EQ::ItemData* item = nullptr;
for (int i = EQ::invslot::EQUIPMENT_BEGIN; i <= EQ::invslot::EQUIPMENT_END; ++i) {
inst = GetBotItem(i);
if(inst) {
for (int slot_id = EQ::invslot::EQUIPMENT_BEGIN; slot_id <= EQ::invslot::EQUIPMENT_END; ++slot_id) {
inst = GetBotItem(slot_id);
if (inst) {
item = inst->GetItem();
BotTradeAddItem(inst->GetID(), inst, inst->GetCharges(), item->Slots, i, errorMessage, false);
if(!errorMessage->empty())
BotTradeAddItem(inst, slot_id, error_message, false);
if (!error_message->empty()) {
return;
}
}
}
UpdateEquipmentLight();

View File

@ -170,7 +170,7 @@ public:
virtual void SetLevel(uint8 in_level, bool command = false);
virtual void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho);
virtual bool Process();
void FinishTrade(Client* client, BotTradeType tradeType);
void FinishTrade(Client* client, BotTradeType trade_type);
virtual bool Save();
virtual void Depop();
void CalcBotStats(bool showtext = true);
@ -344,8 +344,8 @@ public:
virtual bool DoCastSpell(uint16 spell_id, uint16 target_id, EQ::spells::CastingSlot slot = EQ::spells::CastingSlot::Item, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF, uint32 aa_id = 0);
// Bot Equipment & Inventory Class Methods
void BotTradeAddItem(uint32 id, const EQ::ItemInstance* inst, int16 charges, uint32 equipableSlots, uint16 lootSlot, std::string* errorMessage, bool addToDb = true);
void EquipBot(std::string* errorMessage);
void BotTradeAddItem(const EQ::ItemInstance* inst, uint16 slot_id, std::string* error_message, bool save_to_database = true);
void EquipBot(std::string* error_message);
bool CheckLoreConflict(const EQ::ItemData* item);
virtual void UpdateEquipmentLight() { m_Light.Type[EQ::lightsource::LightEquipment] = m_inv.FindBrightestLightType(); m_Light.Level[EQ::lightsource::LightEquipment] = EQ::lightsource::TypeToLevel(m_Light.Type[EQ::lightsource::LightEquipment]); }
const EQ::InventoryProfile& GetBotInv() const { return m_inv; }
@ -355,7 +355,7 @@ public:
static Bot* LoadBot(uint32 botID);
static uint32 SpawnedBotCount(uint32 botOwnerCharacterID);
static void LevelBotWithClient(Client* client, uint8 level, bool sendlvlapp);
//static bool SetBotOwnerCharacterID(uint32 botID, uint32 botOwnerCharacterID, std::string* errorMessage);
//static bool SetBotOwnerCharacterID(uint32 botID, uint32 botOwnerCharacterID, std::string* error_message);
static bool IsBotAttackAllowed(Mob* attacker, Mob* target, bool& hasRuleDefined);
static Bot* GetBotByBotClientOwnerAndBotName(Client* c, std::string botName);
static void ProcessBotGroupInvite(Client* c, std::string botName);
@ -416,7 +416,7 @@ public:
uint32 GetBotSpellID() { return npc_spells_id; }
Mob* GetBotOwner() { return this->_botOwner; }
uint32 GetBotArcheryRange();
EQ::ItemInstance* GetBotItem(uint32 slotID);
EQ::ItemInstance* GetBotItem(uint16 slot_id);
virtual bool GetSpawnStatus() { return _spawnStatus; }
uint8 GetPetChooserID() { return _petChooserID; }
bool IsPetChooser() { return _petChooser; }
@ -571,8 +571,23 @@ public:
// Publicized private functions
static NPCType *FillNPCTypeStruct(uint32 botSpellsID, std::string botName, std::string botLastName, uint8 botLevel, uint16 botRace, uint8 botClass, uint8 gender, float size, uint32 face, uint32 hairStyle, uint32 hairColor, uint32 eyeColor, uint32 eyeColor2, uint32 beardColor, uint32 beard, uint32 drakkinHeritage, uint32 drakkinTattoo, uint32 drakkinDetails, int32 hp, int32 mana, int32 mr, int32 cr, int32 dr, int32 fr, int32 pr, int32 corrup, int32 ac, uint32 str, uint32 sta, uint32 dex, uint32 agi, uint32 _int, uint32 wis, uint32 cha, uint32 attack);
void BotRemoveEquipItem(int16 slot);
void RemoveBotItemBySlot(uint32 slotID, std::string* errorMessage);
void BotRemoveEquipItem(uint16 slot_id);
void RemoveBotItemBySlot(uint16 slot_id, std::string* error_message);
void AddItem(
uint16 slot_id,
uint32 item_id,
int16 charges = -1,
bool attuned = false,
uint32 augment_one = 0,
uint32 augment_two = 0,
uint32 augment_three = 0,
uint32 augment_four = 0,
uint32 augment_five = 0,
uint32 augment_six = 0
);
uint32 CountItem(uint32 item_id);
bool HasItem(uint32 item_id);
void RemoveItem(uint32 item_id);
uint32 GetTotalPlayTime();
// New accessors for BotDatabase access
@ -714,9 +729,9 @@ private:
void SetReturningFlag(bool flag = true) { m_returning_flag = flag; }
// Private "Inventory" Methods
void GetBotItems(EQ::InventoryProfile &inv, std::string* errorMessage);
void BotAddEquipItem(int slot, uint32 id);
uint32 GetBotItemBySlot(uint32 slotID);
void GetBotItems(EQ::InventoryProfile &inv, std::string* error_message);
void BotAddEquipItem(uint16 slot_id, uint32 item_id);
uint32 GetBotItemBySlot(uint16 slot_id);
// Private "Pet" Methods
bool LoadPet(); // Load and spawn bot pet if there is one

File diff suppressed because it is too large Load Diff

View File

@ -6,10 +6,90 @@
#include "bot.h"
#include "lua_bot.h"
#include "lua_mob.h"
void Lua_Bot::AddItem(uint16 slot_id, uint32 item_id) {
Lua_Safe_Call_Void();
self->AddItem(slot_id, item_id);
}
void Lua_Bot::AddItem(uint16 slot_id, uint32 item_id, int16 charges) {
Lua_Safe_Call_Void();
self->AddItem(slot_id, item_id, charges);
}
void Lua_Bot::AddItem(uint16 slot_id, uint32 item_id, int16 charges, bool attuned) {
Lua_Safe_Call_Void();
self->AddItem(slot_id, item_id, charges, attuned);
}
void Lua_Bot::AddItem(uint16 slot_id, uint32 item_id, int16 charges, bool attuned, uint32 augment_one) {
Lua_Safe_Call_Void();
self->AddItem(slot_id, item_id, charges, attuned, augment_one);
}
void Lua_Bot::AddItem(uint16 slot_id, uint32 item_id, int16 charges, bool attuned, uint32 augment_one, uint32 augment_two) {
Lua_Safe_Call_Void();
self->AddItem(slot_id, item_id, charges, attuned, augment_one, augment_two);
}
void Lua_Bot::AddItem(uint16 slot_id, uint32 item_id, int16 charges, bool attuned, uint32 augment_one, uint32 augment_two, uint32 augment_three) {
Lua_Safe_Call_Void();
self->AddItem(slot_id, item_id, charges, attuned, augment_one, augment_two, augment_three);
}
void Lua_Bot::AddItem(uint16 slot_id, uint32 item_id, int16 charges, bool attuned, uint32 augment_one, uint32 augment_two, uint32 augment_three, uint32 augment_four) {
Lua_Safe_Call_Void();
self->AddItem(slot_id, item_id, charges, attuned, augment_one, augment_two, augment_three, augment_four);
}
void Lua_Bot::AddItem(uint16 slot_id, uint32 item_id, int16 charges, bool attuned, uint32 augment_one, uint32 augment_two, uint32 augment_three, uint32 augment_four, uint32 augment_five) {
Lua_Safe_Call_Void();
self->AddItem(slot_id, item_id, charges, attuned, augment_one, augment_two, augment_three, augment_four, augment_five);
}
void Lua_Bot::AddItem(uint16 slot_id, uint32 item_id, int16 charges, bool attuned, uint32 augment_one, uint32 augment_two, uint32 augment_three, uint32 augment_four, uint32 augment_five, uint32 augment_six) {
Lua_Safe_Call_Void();
self->AddItem(slot_id, item_id, charges, attuned, augment_one, augment_two, augment_three, augment_four, augment_five, augment_six);
}
uint32 Lua_Bot::CountItem(uint32 item_id) {
Lua_Safe_Call_Int();
return self->CountItem(item_id);
}
Lua_Mob Lua_Bot::GetOwner() {
Lua_Safe_Call_Class(Lua_Mob);
return Lua_Mob(self->GetOwner());
}
bool Lua_Bot::HasItem(uint32 item_id) {
Lua_Safe_Call_Bool();
return self->HasItem(item_id);
}
void Lua_Bot::RemoveItem(uint32 item_id) {
Lua_Safe_Call_Void();
self->RemoveItem(item_id);
}
luabind::scope lua_register_bot() {
return luabind::class_<Lua_Bot, Lua_Mob>("Bot").def(luabind::constructor<>());
return luabind::class_<Lua_Bot, Lua_Mob>("Bot")
.def(luabind::constructor<>())
.def("AddItem", (void(Lua_Bot::*)(uint16,uint32))&Lua_Bot::AddItem)
.def("AddItem", (void(Lua_Bot::*)(uint16,uint32,int16))&Lua_Bot::AddItem)
.def("AddItem", (void(Lua_Bot::*)(uint16,uint32,int16,bool))&Lua_Bot::AddItem)
.def("AddItem", (void(Lua_Bot::*)(uint16,uint32,int16,bool,uint32))&Lua_Bot::AddItem)
.def("AddItem", (void(Lua_Bot::*)(uint16,uint32,int16,bool,uint32,uint32))&Lua_Bot::AddItem)
.def("AddItem", (void(Lua_Bot::*)(uint16,uint32,int16,bool,uint32,uint32,uint32))&Lua_Bot::AddItem)
.def("AddItem", (void(Lua_Bot::*)(uint16,uint32,int16,bool,uint32,uint32,uint32,uint32))&Lua_Bot::AddItem)
.def("AddItem", (void(Lua_Bot::*)(uint16,uint32,int16,bool,uint32,uint32,uint32,uint32,uint32))&Lua_Bot::AddItem)
.def("AddItem", (void(Lua_Bot::*)(uint16,uint32,int16,bool,uint32,uint32,uint32,uint32,uint32,uint32))&Lua_Bot::AddItem)
.def("CountItem", (uint32(Lua_Bot::*)(uint32))&Lua_Bot::CountItem)
.def("GetOwner", (Lua_Mob(Lua_Bot::*)(void))&Lua_Bot::GetOwner)
.def("HasItem", (bool(Lua_Bot::*)(uint32))&Lua_Bot::HasItem)
.def("RemoveItem", (void(Lua_Bot::*)(uint32))&Lua_Bot::RemoveItem);
}
#endif
#endif
#endif

View File

@ -7,6 +7,7 @@
class Bot;
class Lua_Bot;
class Lua_Mob;
namespace luabind {
struct scope;
@ -25,6 +26,20 @@ public:
operator Bot*() {
return reinterpret_cast<Bot*>(GetLuaPtrData());
}
void AddItem(uint16 slot_id, uint32 item_id);
void AddItem(uint16 slot_id, uint32 item_id, int16 charges);
void AddItem(uint16 slot_id, uint32 item_id, int16 charges, bool attuned);
void AddItem(uint16 slot_id, uint32 item_id, int16 charges, bool attuned, uint32 augment_one);
void AddItem(uint16 slot_id, uint32 item_id, int16 charges, bool attuned, uint32 augment_one, uint32 augment_two);
void AddItem(uint16 slot_id, uint32 item_id, int16 charges, bool attuned, uint32 augment_one, uint32 augment_two, uint32 augment_three);
void AddItem(uint16 slot_id, uint32 item_id, int16 charges, bool attuned, uint32 augment_one, uint32 augment_two, uint32 augment_three, uint32 augment_four);
void AddItem(uint16 slot_id, uint32 item_id, int16 charges, bool attuned, uint32 augment_one, uint32 augment_two, uint32 augment_three, uint32 augment_four, uint32 augment_five);
void AddItem(uint16 slot_id, uint32 item_id, int16 charges, bool attuned, uint32 augment_one, uint32 augment_two, uint32 augment_three, uint32 augment_four, uint32 augment_five, uint32 augment_six);
uint32 CountItem(uint32 item_id);
Lua_Mob GetOwner();
bool HasItem(uint32 item_id);
void RemoveItem(uint32 item_id);
};
#endif

View File

@ -44,6 +44,111 @@ XS(XS_Bot_GetOwner)
XSRETURN(1);
}
XS(XS_Bot_AddItem); /* prototype to pass -Wmissing-prototypes */
XS(XS_Bot_AddItem) {
dXSARGS;
if (items < 3 || items > 11)
Perl_croak(aTHX_ "Usage: Bot::AddItem(THIS, uint16 slot_id, uint32 item_id, [int16 charges = -1], [bool attuned = false], [uint32 augment_one = 0], [uint32 augment_two = 0], [uint32 augment_three = 0], [uint32 augment_four = 0], [uint32 augment_five = 0], [uint32 augment_six = 0])"); // @categories Inventory and Items, Script Utility
{
Bot* THIS;
uint16 slot_id = (uint16) SvUV(ST(1));
uint32 item_id = (uint32) SvUV(ST(2));
int16 charges = -1;
bool attuned = false;
uint32 augment_one = 0;
uint32 augment_two = 0;
uint32 augment_three = 0;
uint32 augment_four = 0;
uint32 augment_five = 0;
uint32 augment_six = 0;
VALIDATE_THIS_IS_BOT;
if (items > 3) {
charges = (int16) SvIV(ST(3));
}
if (items > 4) {
attuned = (bool) SvTRUE(ST(4));
}
if (items > 5) {
augment_one = (uint32) SvUV(ST(5));
}
if (items > 6) {
augment_two = (uint32) SvUV(ST(6));
}
if (items > 7) {
augment_three = (uint32) SvUV(ST(7));
}
if (items > 8) {
augment_four = (uint32) SvUV(ST(8));
}
if (items > 9) {
augment_five = (uint32) SvUV(ST(9));
}
if (items > 10) {
augment_six = (uint32) SvUV(ST(10));
}
THIS->AddItem(slot_id, item_id, charges, attuned, augment_one, augment_two, augment_three, augment_four, augment_five, augment_six);
}
XSRETURN_EMPTY;
}
XS(XS_Bot_CountItem);
XS(XS_Bot_CountItem) {
dXSARGS;
if (items != 2)
Perl_croak(aTHX_ "Usage: Bot::CountItem(THIS, uint32 item_id)");
{
Bot* THIS;
int item_count = 0;
uint32 item_id = (uint32) SvUV(ST(1));
dXSTARG;
VALIDATE_THIS_IS_BOT;
item_count = THIS->CountItem(item_id);
XSprePUSH;
PUSHu((UV) item_count);
}
XSRETURN(1);
}
XS(XS_Bot_HasItem);
XS(XS_Bot_HasItem) {
dXSARGS;
if (items != 2)
Perl_croak(aTHX_ "Usage: Bot:HasItem(THIS, uint32 item_id)");
{
Bot* THIS;
bool has_item = false;
uint32 item_id = (uint32) SvUV(ST(1));
VALIDATE_THIS_IS_BOT;
has_item = THIS->HasItem(item_id);
ST(0) = boolSV(has_item);
sv_2mortal(ST(0));
}
XSRETURN(1);
}
XS(XS_Bot_RemoveItem);
XS(XS_Bot_RemoveItem) {
dXSARGS;
if (items != 2)
Perl_croak(aTHX_ "Usage: Bot::RemoveItem(THIS, uint32 item_id)"); // @categories Spells and Disciplines
{
Bot* THIS;
uint32 item_id = (uint32) SvUV(ST(1));
VALIDATE_THIS_IS_BOT;
THIS->RemoveItem(item_id);
}
XSRETURN_EMPTY;
}
#ifdef __cplusplus
extern "C"
#endif
@ -62,9 +167,13 @@ XS(boot_Bot)
char buf[128];
XS_VERSION_BOOTCHECK;
newXSproto(strcpy(buf, "AddItem"), XS_Bot_AddItem, file, "$$$;$$$$$$$$");
newXSproto(strcpy(buf, "CountItem"), XS_Bot_CountItem, file, "$$");
newXSproto(strcpy(buf, "GetOwner"), XS_Bot_GetOwner, file, "$");
newXSproto(strcpy(buf, "HasItem"), XS_Bot_HasItem, file, "$$");
newXSproto(strcpy(buf, "RemoveItem"), XS_Bot_RemoveItem, file, "$$");
XSRETURN_YES;
}
#endif //EMBPERL_XS_CLASSES
#endif //BOTS
#endif //BOTS