Skip to content

Commit

Permalink
First implementation.
Browse files Browse the repository at this point in the history
  • Loading branch information
AnchyDev committed Oct 6, 2023
1 parent 1cc4283 commit 3c80e22
Show file tree
Hide file tree
Showing 7 changed files with 360 additions and 50 deletions.
2 changes: 1 addition & 1 deletion conf/my_custom.conf.dist → conf/attriboost.conf.dist
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@
# 1 - Enabled
#

MyModule.Enable = 1
Attriboost.Enable = 1
14 changes: 14 additions & 0 deletions data/sql/db-world/base/base.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
UPDATE item_template
SET
name = "Book of Knowledge",
description = "|cff00FF00Use: Increases a random attribute related to your class.|cffF7B500",
BuyPrice = 0,
SellPrice = 0,
RequiredSkill = 0,
RequiredSkillRank = 0,
RequiredLevel = 1,
ItemLevel = 1,
Stackable = 200,
spellid_1 = 18282,
bonding = 1
WHERE entry = 16073;
4 changes: 0 additions & 4 deletions data/sql/db-world/base/skeleton_module_acore_string.sql

This file was deleted.

281 changes: 281 additions & 0 deletions src/Attriboost.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,281 @@
#include "Attriboost.h"

#include "Chat.h"
#include "Config.h"
#include "Spell.h"

void AttriboostPlayerScript::OnLogin(Player* player)
{
if (!player)
{
return;
}

if (!sConfigMgr->GetOption<bool>("Attriboost.Enable", false))
{
return;
}

auto attributes = GetAttriboosts(player->GetGUID().GetRawValue());
ApplyAttributes(player, attributes);
}

bool AttriboostPlayerScript::CanUseItem(Player* player, ItemTemplate const* proto, InventoryResult& /*result*/)
{
if (!proto)
{
return true;
}

if (proto->ItemId != ATTR_ITEM)
{
return true;
}

if (!sConfigMgr->GetOption<bool>("Attriboost.Enable", false))
{
ChatHandler(player->GetSession()).SendSysMessage("This item is disabled.");
return false;
}

auto attribute = GetRandomAttributeForClass(player);
if (!attribute)
{
LOG_WARN("module", "Failed to get random attribute for player '{}'.", player->GetName());
return false;
}

auto attributes = GetAttriboosts(player->GetGUID().GetRawValue());
AddAttribute(attributes, attribute);
ApplyAttributes(player, attributes);

auto attributeName = GetAttributeName(attribute);
if (!attributeName.empty())
{
ChatHandler(player->GetSession()).SendSysMessage(Acore::StringFormatFmt("Increased {} by 1.", GetAttributeName(attribute)));
}

player->DestroyItemCount(ATTR_ITEM, 1, true);

return true;
}

uint32 AttriboostPlayerScript::GetRandomAttributeForClass(Player* player)
{
switch (player->getClass())
{
case CLASS_ROGUE:
switch (urand(0, 2))
{
case 0:
return ATTR_SPELL_STAMINA;
case 1:
return ATTR_SPELL_AGILITY;
case 2:
return ATTR_SPELL_STRENGTH;
}
}

return 0;
}

std::string AttriboostPlayerScript::GetAttributeName(uint32 attribute)
{
switch (attribute)
{
case ATTR_SPELL_STAMINA:
return "Stamina";

case ATTR_SPELL_STRENGTH:
return "Strength";

case ATTR_SPELL_AGILITY:
return "Agility";

case ATTR_SPELL_INTELLECT:
return "Intellect";

case ATTR_SPELL_SPIRIT:
return "Spirit";
}

return std::string();
}

Attriboosts* GetAttriboosts(uint64 guid)
{
auto attri = attriboostsMap.find(guid);
if (attri == attriboostsMap.end())
{
Attriboosts attriboosts;
attriboosts.Stamina = 0;
attriboosts.Strength = 0;
attriboosts.Agility = 0;
attriboosts.Intellect = 0;
attriboosts.Spirit = 0;

auto result = attriboostsMap.emplace(guid, attriboosts);
attri = result.first;
}

return &attri->second;
}

void ClearAttriboosts()
{
attriboostsMap.clear();
}

void LoadAttriboosts()
{
auto qResult = CharacterDatabase.Query("SELECT * FROM attriboost_attributes");

if (!qResult)
{
LOG_ERROR("module", "Failed to load from 'attriboost_attributes' table.");
return;
}

LOG_INFO("module", "Loading player attriboosts from 'attriboost_attributes'..");

int count = 0;

do
{
auto fields = qResult->Fetch();

uint64 guid = fields[0].Get<uint64>();

Attriboosts attriboosts;
attriboosts.Stamina = fields[1].Get<uint64>();
attriboosts.Strength = fields[2].Get<uint64>();
attriboosts.Agility = fields[3].Get<uint64>();
attriboosts.Intellect = fields[4].Get<uint64>();
attriboosts.Spirit = fields[5].Get<uint64>();

attriboostsMap.emplace(guid, attriboosts);

count++;
} while (qResult->NextRow());

LOG_INFO("module", "Loaded '{}' player attriboosts.", count);
}

void SaveAttriboosts()
{
for (auto it = attriboostsMap.begin(); it != attriboostsMap.end(); ++it)
{
auto guid = it->first;

auto stamina = it->second.Stamina;
auto strength = it->second.Strength;
auto agility = it->second.Agility;
auto intellect = it->second.Intellect;
auto spirit = it->second.Spirit;

CharacterDatabase.Execute("INSERT INTO `attriboost_attributes` (guid, stamina, strength, agility, intellect, spirit) VALUES ({}, {}, {}, {}, {}, {}) ON DUPLICATE KEY UPDATE stamina={}, strength={}, agility={}, intellect={}, spirit={}",
guid,
stamina, strength, agility, intellect, spirit,
stamina, strength, agility, intellect, spirit);
}
}

void ApplyAttributes(Player* player, Attriboosts* attributes)
{
if (attributes->Stamina > 0)
{
auto stamina = player->GetAura(ATTR_SPELL_STAMINA);
if (!stamina)
{
stamina = player->AddAura(ATTR_SPELL_STAMINA, player);
}
stamina->SetStackAmount(attributes->Stamina);
}

if (attributes->Strength > 0)
{
auto strength = player->GetAura(ATTR_SPELL_STRENGTH);
if (!strength)
{
strength = player->AddAura(ATTR_SPELL_STRENGTH, player);
}
strength->SetStackAmount(attributes->Strength);
}

if (attributes->Agility > 0)
{
auto agility = player->GetAura(ATTR_SPELL_AGILITY);
if (!agility)
{
agility = player->AddAura(ATTR_SPELL_AGILITY, player);
}
agility->SetStackAmount(attributes->Agility);
}

if (attributes->Intellect > 0)
{
auto intellect = player->GetAura(ATTR_SPELL_INTELLECT);
if (!intellect)
{
intellect = player->AddAura(ATTR_SPELL_INTELLECT, player);
}
intellect->SetStackAmount(attributes->Intellect);
}

if (attributes->Spirit > 0)
{
auto spirit = player->GetAura(ATTR_SPELL_SPIRIT);
if (!spirit)
{
spirit = player->AddAura(ATTR_SPELL_SPIRIT, player);
}
spirit->SetStackAmount(attributes->Spirit);
}
}

void AddAttribute(Attriboosts* attributes, uint32 attribute)
{
switch (attribute)
{
case ATTR_SPELL_STAMINA:
attributes->Stamina += 1;
break;

case ATTR_SPELL_STRENGTH:
attributes->Strength += 1;
break;

case ATTR_SPELL_AGILITY:
attributes->Agility += 1;
break;

case ATTR_SPELL_INTELLECT:
attributes->Intellect += 1;
break;

case ATTR_SPELL_SPIRIT:
attributes->Spirit += 1;
break;
}
}

void AttriboostWorldScript::OnAfterConfigLoad(bool reload)
{
if (reload)
{
ClearAttriboosts();
}

LoadAttriboosts();
}

void AttriboostWorldScript::OnShutdownInitiate(ShutdownExitCode /*code*/, ShutdownMask /*mask*/)
{
SaveAttriboosts();
}

void SC_AddAttriboostScripts()
{
new AttriboostWorldScript();
new AttriboostPlayerScript();
}
61 changes: 61 additions & 0 deletions src/Attriboost.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#ifndef MODULE_ATTRIBOOST_H
#define MODULE_ATTRIBOOST_H

#include "ScriptMgr.h"
#include "Player.h"

#include <unordered_map>

enum AttriboostItems
{
ATTR_ITEM = 16073
};

enum AttriboostStats
{
ATTR_SPELL_STAMINA = 7477,
ATTR_SPELL_AGILITY = 7471,
ATTR_SPELL_INTELLECT = 7468,
ATTR_SPELL_STRENGTH = 7464,
ATTR_SPELL_SPIRIT = 7474
};

struct Attriboosts
{
uint32 Stamina;
uint32 Strength;
uint32 Agility;
uint32 Intellect;
uint32 Spirit;
};

std::unordered_map<uint64, Attriboosts> attriboostsMap;

Attriboosts* GetAttriboosts(uint64 /*guid*/);
void ClearAttriboosts();
void LoadAttriboosts();
void ApplyAttributes(Player* /*player*/, Attriboosts* /*attributes*/);
void AddAttribute(Attriboosts* /*attributes*/, uint32 /*attribute*/);

class AttriboostPlayerScript : public PlayerScript
{
public:
AttriboostPlayerScript() : PlayerScript("AttriboostPlayerScript") { }

virtual void OnLogin(Player* /*player*/) override;
virtual bool CanUseItem(Player* /*player*/, ItemTemplate const* /*proto*/, InventoryResult& /*result*/) override;

uint32 GetRandomAttributeForClass(Player* /*player*/);
std::string GetAttributeName(uint32 /*attribute*/);
};

class AttriboostWorldScript : public WorldScript
{
public:
AttriboostWorldScript() : WorldScript("AttriboostWorldScript") { }

virtual void OnAfterConfigLoad(bool /*reload*/) override;
virtual void OnShutdownInitiate(ShutdownExitCode /*code*/, ShutdownMask /*mask*/) override;
};

#endif // MODULE_ATTRIBOOST_H
14 changes: 3 additions & 11 deletions src/MP_loader.cpp
Original file line number Diff line number Diff line change
@@ -1,15 +1,7 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3
*/
void SC_AddAttriboostScripts();

// From SC
void AddMyPlayerScripts();

// Add all
// cf. the naming convention https://github.com/azerothcore/azerothcore-wotlk/blob/master/doc/changelog/master.md#how-to-upgrade-4
// additionally replace all '-' in the module folder name with '_' here
void Addskeleton_moduleScripts()
void AddAttriboostScripts()
{
AddMyPlayerScripts();
SC_AddAttriboostScripts();
}

Loading

0 comments on commit 3c80e22

Please sign in to comment.