initial ver

master
Dominik Madarász 2024-06-21 13:14:43 +02:00
parent 76d04c8dae
commit aab757e2e3
10 changed files with 365 additions and 70 deletions

View File

@ -0,0 +1,9 @@
NeedsSystem.Enable = 1
NeedsSystem.MaxValue = 255
NeedsSystem.LowValue = 16
NeedsSystem.CriticalValue = 5
NeedsSystem.DropRate = 60
NeedsSystem.DropValueHunger = 1
NeedsSystem.DropValueThirst = 1
NeedsSystem.NewPlayerHunger = 64
NeedsSystem.NewPlayerThirst = 64

View File

@ -1,17 +0,0 @@
#
# Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3
#
[worldserver]
########################################
# My module configuration
########################################
#
# MyModule.Enable
# Description: Enable my module and print "Hello World" message at server start
# Default: 0 - Disabled
# 1 - Enabled
#
MyModule.Enable = 1

View File

@ -0,0 +1,6 @@
CREATE TABLE `acore_characters`.`mod_needs` (
`guid` INT(10) UNSIGNED NOT NULL DEFAULT '0',
`hunger` TINYINT(3) UNSIGNED NOT NULL DEFAULT '64',
`thirst` TINYINT(3) UNSIGNED NOT NULL DEFAULT '64',
PRIMARY KEY (`guid`) USING BTREE
)

View File

@ -0,0 +1,6 @@
DELETE FROM `command` WHERE `name` IN ('needs', 'needs set', 'needs view');
INSERT INTO `command` (`name`, `security`, `help`) VALUES
('needs', 0, 'Syntax: .needs [subcommand]\nType .help needs to see a list of subcommands\nor .help needs [subcommand] to see info on the subcommand.'),
('needs set', 2, 'Syntax: .needs set [hunger] [thirst]\nSet your current hunger and thirst levels.'),
('needs view', 0, 'Syntax: .needs view\nView your current needs levels.');

View File

@ -0,0 +1,7 @@
CREATE TABLE `mod_sustenance` (
`guid` INT(10) UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Item ID',
`hunger` SMALLINT(6) NULL DEFAULT NULL,
`thirst` SMALLINT(6) NULL DEFAULT NULL,
PRIMARY KEY (`guid`) USING BTREE
)

View File

@ -1,4 +0,0 @@
SET @ENTRY:=35410;
DELETE FROM `acore_string` WHERE `entry`=@ENTRY;
INSERT INTO `acore_string` (`entry`, `content_default`, `locale_koKR`, `locale_frFR`, `locale_deDE`, `locale_zhCN`, `locale_zhTW`, `locale_esES`, `locale_esMX`, `locale_ruRU`) VALUES
(@ENTRY, 'Hello World from Skeleton-Module!', '', '', '', '', '', '¡Hola Mundo desde Skeleton-Module!', '¡Hola Mundo desde Skeleton-Module!', '');

View File

@ -1,15 +0,0 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3
*/
// 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()
{
AddMyPlayerScripts();
}

View File

@ -1,34 +0,0 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3
*/
#include "ScriptMgr.h"
#include "Player.h"
#include "Config.h"
#include "Chat.h"
enum MyPlayerAcoreString
{
HELLO_WORLD = 35410
};
// Add player scripts
class MyPlayer : public PlayerScript
{
public:
MyPlayer() : PlayerScript("MyPlayer") { }
void OnLogin(Player* player) override
{
if (sConfigMgr->GetOption<bool>("MyModule.Enable", false))
{
ChatHandler(player->GetSession()).PSendSysMessage(HELLO_WORLD);
}
}
};
// Add all scripts in one
void AddMyPlayerScripts()
{
new MyPlayer();
}

330
src/NeedsSystem.cpp 100644
View File

@ -0,0 +1,330 @@
#include "ScriptMgr.h"
#include "SpellScript.h"
#include "Player.h"
#include "Config.h"
#include "Chat.h"
#include "Object.h"
#include "DataMap.h"
#include <unordered_map>
using namespace Acore::ChatCommands;
bool NeedsEnabled = true;
uint8 NeedsMaxValue = 255;
uint8 NeedsLowValue = 16;
uint8 NeedsCriticalValue = 5;
uint32 NeedsDropRate = 60;
uint8 NeedsDropValueHunger = 1;
uint8 NeedsDropValueThirst = 1;
uint8 NeedsNewPlayerHunger = 64;
uint8 NeedsNewPlayerThirst = 64;
#define NEEDS_TICK (NeedsDropRate * 1000)
enum
{
SPELL_MILDLY_HUNGRY = 1000000,
SPELL_MILDLY_THIRSTY,
SPELL_HUNGRY,
SPELL_THIRSTY,
SPELL_STARVING,
SPELL_PARCHED,
};
struct SustenanceData
{
SustenanceData() {}
SustenanceData(int16 hunger, int16 thirst): hunger(hunger), thirst(thirst) {}
int16 hunger = 0;
int16 thirst = 0;
};
std::unordered_map<uint32, SustenanceData> Sustenance;
class NeedsConf: public WorldScript
{
public:
NeedsConf() : WorldScript("NeedsConf") {}
void OnBeforeConfigLoad(bool /* reload */) override
{
NeedsEnabled = sConfigMgr->GetOption<bool>("NeedsSystem.Enabled", true);
NeedsMaxValue = sConfigMgr->GetOption<uint8>("NeedsSystem.MaxValue", 255);
NeedsLowValue = sConfigMgr->GetOption<uint8>("NeedsSystem.LowValue", 16);
NeedsCriticalValue = sConfigMgr->GetOption<uint8>("NeedsSystem.CriticalValue", 5);
NeedsDropRate = sConfigMgr->GetOption<uint32>("NeedsSystem.DropRate", 60);
NeedsDropValueHunger = sConfigMgr->GetOption<uint8>("NeedsSystem.DropValueHunger", 1);
NeedsDropValueThirst = sConfigMgr->GetOption<uint8>("NeedsSystem.DropValueThirst", 1);
NeedsNewPlayerHunger = sConfigMgr->GetOption<uint8>("NeedsSystem.NewPlayerHunger", 64);
NeedsNewPlayerThirst = sConfigMgr->GetOption<uint8>("NeedsSystem.NewPlayerThirst", 64);
}
void OnStartup() override
{
LOG_INFO("server.loading", "Loading sustenance...");
uint32 msTime = getMSTime();
QueryResult result = WorldDatabase.Query("SELECT `guid`,`hunger`,`thirst` FROM `mod_sustenance`");
if (!result)
{
LOG_ERROR("server.loading", "MySQL table 'mod_sustenance' is missing from the world DB or is empty!");
NeedsEnabled = false;
return;
}
uint32 count = 0;
do
{
Field* fields = result->Fetch();
Sustenance[fields[0].Get<uint32>()] = SustenanceData(fields[1].Get<int16>(), fields[2].Get<int16>());
++count;
}
while (result->NextRow());
LOG_INFO("server.loading", "Loaded {} sustenance in {} ms", count, GetMSTimeDiffToNow(msTime));
}
};
class PlayerNeeds: public DataMap::Base
{
public:
PlayerNeeds() {}
PlayerNeeds(uint8 hunger, uint8 thirst): hunger(hunger), thirst(thirst)
{
nextTick = getMSTime() + NEEDS_TICK;
}
uint8 hunger = 64;
uint8 thirst = 64;
uint32 nextTick = 0;
};
class NeedsSystem : public PlayerScript
{
public:
NeedsSystem() : PlayerScript("NeedsSystemScript") { }
void OnLogin(Player* player) override
{
QueryResult result = CharacterDatabase.Query("SELECT `hunger`,`thirst` FROM `mod_needs` WHERE `guid`='{}'", player->GetGUID().GetCounter());
if (!result)
{
PlayerNeeds *defaultNeeds = player->CustomData.GetDefault<PlayerNeeds>("Needs");
defaultNeeds->hunger = NeedsNewPlayerHunger;
defaultNeeds->thirst = NeedsNewPlayerThirst;
defaultNeeds->nextTick = getMSTime() + NEEDS_TICK;
}
else
{
Field* fields = result->Fetch();
player->CustomData.Set("Needs", new PlayerNeeds(fields[0].Get<uint8>(), fields[1].Get<uint8>()));
}
}
void SaveData(Player* player)
{
if (PlayerNeeds* data = player->CustomData.Get<PlayerNeeds>("Needs"))
{
CharacterDatabase.DirectExecute("REPLACE INTO `mod_needs` (`guid`,`hunger`,`thirst`) VALUES ('{}', '{}', '{}');", player->GetGUID().GetCounter(), data->hunger, data->thirst);
}
}
void OnLogout(Player* player) override
{
SaveData(player);
}
static void HandleBuffs(Player* player, PlayerNeeds *needs)
{
player->RemoveOwnedAura(SPELL_MILDLY_HUNGRY);
player->RemoveOwnedAura(SPELL_MILDLY_THIRSTY);
player->RemoveOwnedAura(SPELL_HUNGRY);
player->RemoveOwnedAura(SPELL_THIRSTY);
player->RemoveOwnedAura(SPELL_STARVING);
player->RemoveOwnedAura(SPELL_PARCHED);
if (!player->IsAlive())
{
return;
}
if (needs->hunger == 0)
{
player->CastSpell(player, SPELL_STARVING, true);
}
else if (needs->hunger <= NeedsCriticalValue)
{
player->CastSpell(player, SPELL_HUNGRY, true);
}
else if (needs->hunger <= NeedsLowValue)
{
player->CastSpell(player, SPELL_MILDLY_HUNGRY, true);
}
if (needs->thirst == 0)
{
player->CastSpell(player, SPELL_PARCHED, true);
}
else if (needs->thirst <= NeedsCriticalValue)
{
player->CastSpell(player, SPELL_THIRSTY, true);
}
else if (needs->thirst <= NeedsLowValue)
{
player->CastSpell(player, SPELL_MILDLY_THIRSTY, true);
}
}
void OnSpellCast(Player* player, Spell* spell, bool /*skipCheck*/) override
{
if (!NeedsEnabled || !spell->m_CastItem)
{
return;
}
uint32 itemId = spell->m_CastItem->GetTemplate()->ItemId;
if (Sustenance.find(itemId) != Sustenance.end())
{
SustenanceData data = Sustenance[itemId];
PlayerNeeds *needs = player->CustomData.Get<PlayerNeeds>("Needs");
int32 hungerVal = needs->hunger;
int32 thirstVal = needs->thirst;
if (hungerVal + data.hunger < 0)
needs->hunger = 0;
else if (hungerVal + data.hunger > NeedsMaxValue)
needs->hunger = NeedsMaxValue;
else
needs->hunger += data.hunger;
if (thirstVal + data.thirst < 0)
needs->thirst = 0;
else if (thirstVal + data.thirst > NeedsMaxValue)
needs->thirst = NeedsMaxValue;
else
needs->thirst += data.thirst;
ChatHandler(player->GetSession()).PSendSysMessage("You feel invirogated!\nCurrent needs:\nHunger: %d\nThirst: %d", needs->hunger, needs->thirst);
HandleBuffs(player, needs);
}
}
void OnBeforeUpdate(Player* player, uint32 /* p_time */) override
{
if (!NeedsEnabled || !player->IsInWorld() || !player->IsAlive())
{
return;
}
PlayerNeeds *needs = player->CustomData.Get<PlayerNeeds>("Needs");
if (needs->nextTick < getMSTime())
{
needs->nextTick = getMSTime() + NEEDS_TICK;
int32 hungerVal = needs->hunger;
int32 thirstVal = needs->thirst;
if (hungerVal - NeedsDropValueHunger < 0)
needs->hunger = 0;
else
needs->hunger -= NeedsDropValueHunger;
if (thirstVal - NeedsDropValueThirst < 0)
needs->thirst = 0;
else
needs->thirst -= NeedsDropValueThirst;
HandleBuffs(player, needs);
}
}
void OnPlayerJustDied(Player* player) override
{
if (!NeedsEnabled || !player->IsInWorld())
{
return;
}
PlayerNeeds *needs = player->CustomData.Get<PlayerNeeds>("Needs");
needs->hunger = NeedsNewPlayerHunger;
needs->thirst = NeedsNewPlayerThirst;
HandleBuffs(player, needs);
}
};
class NeedsCommand : public CommandScript
{
public:
NeedsCommand() : CommandScript("NeedsCommand") {}
ChatCommandTable GetCommands() const override
{
static ChatCommandTable NeedsCommandTable =
{
{ "view", HandleViewCommand, SEC_PLAYER, Console::No },
{ "set", HandleSetCommand, SEC_GAMEMASTER, Console::No },
};
static ChatCommandTable NeedsBaseTable =
{
{ "needs", NeedsCommandTable }
};
return NeedsBaseTable;
}
static bool HandleViewCommand(ChatHandler* handler)
{
if (!NeedsEnabled)
{
handler->PSendSysMessage("Needs system is disabled!");
handler->SetSentErrorMessage(true);
return false;
}
Player* player = handler->GetSession()->GetPlayer();
if (!player)
return false;
PlayerNeeds* needs = player->CustomData.Get<PlayerNeeds>("Needs");
ChatHandler(player->GetSession()).PSendSysMessage("Current needs:\nHunger: %d\nThirst: %d", needs->hunger, needs->thirst);
return true;
}
static bool HandleSetCommand(ChatHandler* handler, uint8 hunger, uint8 thirst)
{
if (!NeedsEnabled)
{
handler->PSendSysMessage("Needs system is disabled!");
handler->SetSentErrorMessage(true);
return false;
}
Player* player = handler->GetSession()->GetPlayer();
if (!player)
return false;
PlayerNeeds* needs = player->CustomData.Get<PlayerNeeds>("Needs");
needs->hunger = hunger;
needs->thirst = thirst;
NeedsSystem::HandleBuffs(player, needs);
ChatHandler(player->GetSession()).PSendSysMessage("Need levels set!");
return true;
}
};
// Add all scripts in one
void AddNeedsSystemScripts()
{
new NeedsConf();
new NeedsSystem();
new NeedsCommand();
}

View File

@ -0,0 +1,7 @@
void AddNeedsSystemScripts();
void Addmod_needs_systemScripts()
{
AddNeedsSystemScripts();
}