eluna-scripts-ornfelt/lua/WowEmulationScriptPack/C++/IronMan/IronMan.cpp
2024-09-23 07:59:23 +02:00

433 lines
15 KiB
C++

#include "SharedDefines.h"
#include "ScriptMgr.h"
#include "GameEventCallbacks.h"
#include "ObjectExtension.cpp"
#include "Player.h"
#include "DatabaseEnv.h"
#include "Creature.h"
#include "Map.h"
#include "ObjectAccessor.h"
#include "worldSession.h"
#include <string.h>
#include "Group.h"
#include "Item.h"
// only IronMan players will have this event handler. We can say to all of them that we do not allow buy items
void IronManHardcoreVendorBuyItem(void *p, void *)
{
CP_VENDOR_BUY_ITEM *params = PointerCast(CP_VENDOR_BUY_ITEM, p);
//can use normal vendors
if (params->Vendor->GetEntry() < 200000)
return;
params->DenyDefaultParsing = 1;
params->Player->BroadcastMessage("Vendor usage is disabled");
}
// only IronMan players will have this event handler. We can say to all of them that we do not allow buy items
void IronManHardcoreMailTakeItem(void *p, void *)
{
CP_ASK_DISABLED_FEATURE_MAIL *params = PointerCast(CP_ASK_DISABLED_FEATURE_MAIL, p);
//maybe this is a system mail ?
if (params->Sender == 0)
return;
//allow GM emails ?
Player* pSender = ObjectAccessor::FindPlayerByLowGUID(params->Sender);
if (pSender != NULL && ( pSender->IsGameMaster() || params->Player == pSender))
return;
params->DenyDefaultParsing = 1;
params->Player->BroadcastMessage("Mail usage is disabled");
}
// only IronMan players will have this event handler. We can say to all of them that we do not allow buy items
void IronManHardcoreTradeAccept(void *p, void *)
{
CP_ASK_DISABLED_FEATURE *params = PointerCast(CP_ASK_DISABLED_FEATURE, p);
params->DenyDefaultParsing = 1;
params->Player->BroadcastMessage("Trading is disabled");
}
// only IronMan players will have this event handler. We can say to all of them that we do not allow buy items
void IronManHardcoreGuildJoin(void *p, void *)
{
CP_ASK_DISABLED_FEATURE *params = PointerCast(CP_ASK_DISABLED_FEATURE, p);
params->DenyDefaultParsing = 1;
params->Player->BroadcastMessage("Guilding is disabled");
}
// only IronMan players will have this event handler. We can say to all of them that we do not allow buy items
void IronManHardcoreGroupJoin(void *p, void *)
{
CP_ASK_DISABLED_FEATURE *params = PointerCast(CP_ASK_DISABLED_FEATURE, p);
params->DenyDefaultParsing = 1;
params->Player->BroadcastMessage("Grouping is disabled");
}
void PeriodicMonitorPlayerStaysDead(void *p, void *);
class IronManHardcoreStore
{
public:
//zero all
IronManHardcoreStore()
{
IsIronMan = IsHardcore = NeedsDBSave = false;
TimesDied = KillerEntry = 0;
}
// mark player as IronMan player
void EnableIronMan(Player *p)
{
if (IsIronMan == false)
{
IsIronMan = true;
p->BroadcastMessage("You can never go back to from ironman mode! There is a special place in hell for you");
p->BroadcastMessage("You no longer can buy items from vendors");
p->BroadcastMessage("You no longer pick items from mails");
p->BroadcastMessage("You no longer buy items from auction");
p->BroadcastMessage("You no longer can join guilds");
p->BroadcastMessage("You no longer can join groups");
p->BroadcastMessage("When you die you lose half of your gold");
NeedsDBSave = true;
SavePlayerData(p);
RegisterIronManScripts(p);
}
}
// mark player as Hardcore player
void EnableHardcore(Player *p)
{
//every hardcore player is an ironman player also
EnableIronMan(p);
//also add hardcore restrictions
if (IsHardcore == false)
{
IsHardcore = true;
p->BroadcastMessage("You can never go back to from hardcore mode!");
p->BroadcastMessage("Once you die, you die forever. Step carefully");
NeedsDBSave = true;
SavePlayerData(p);
RegisterHardcoreScripts(p);
}
}
//register handlers to disable specific game features
void RegisterIronManScripts(Player *p)
{
p->RegisterCallbackFunc(CALLBACK_TYPE_PLAYER_VENDOR_BUY_ITEM, IronManHardcoreVendorBuyItem);
p->RegisterCallbackFunc(CALLBACK_TYPE_PLAYER_TAKE_MAIL_ITEM, IronManHardcoreMailTakeItem);
p->RegisterCallbackFunc(CALLBACK_TYPE_PLAYER_TRADE_ACCEPT, IronManHardcoreTradeAccept);
p->RegisterCallbackFunc(CALLBACK_TYPE_PLAYER_GUILD_JOIN, IronManHardcoreGuildJoin);
}
//register handlers to disable specific game features
void RegisterHardcoreScripts(Player *p)
{
p->RegisterCallbackFunc(CALLBACK_TYPE_PLAYER_GROUP_INVITE, IronManHardcoreGroupJoin);
p->RegisterCallbackFunc(CALLBACK_TYPE_PLAYER_GROUP_ACCEPT, IronManHardcoreGroupJoin);
p->RegisterCallbackFunc(CALLBACK_TYPE_PLAYER_PERIODIC_TICK, PeriodicMonitorPlayerStaysDead);
}
//check if we are Hardcore or not
void LoadPlayerData(Player *p)
{
char Query[5000];
sprintf_s(Query, sizeof(Query), "SELECT IsHardCore,TimesDied from character_IronManHardCore where GUID = %d", (uint32)p->GetGUID().GetRawValue());
QueryResult result = CharacterDatabase.Query(Query);
if (!result || result->GetRowCount() != 1)
return;
Field* fields = result->Fetch();
IsHardcore = (fields[0].GetUInt32() != 0);
TimesDied = fields[1].GetUInt32();
IsIronMan = true;
RegisterIronManScripts(p);
if(IsHardcore==true)
RegisterHardcoreScripts(p);
}
//register player as rionman, or mark him dead if is in hardcore mode
void SavePlayerData(Player *p)
{
if (NeedsDBSave == false)
return;
char Query[5000];
sprintf_s(Query, sizeof(Query), "Replace into character_IronManHardCore values(%d,%d,%d,%d)", (uint32)p->GetGUID().GetRawValue(), (uint32)IsHardcore, TimesDied, KillerEntry);
CharacterDatabase.Execute(Query);
NeedsDBSave = false;
}
void OnDied(Player *p, uint32 pKillerEntry)
{
TimesDied++;
NeedsDBSave = true;
if (IsHardcore == true)
{
KillerEntry = pKillerEntry;
p->BroadcastMessage("You died forever. May your highscores be remembered forever");
SavePlayerData(p);
}
//death takes it's toll. Half money lost
p->SetMoney(p->GetMoney() / 2);
}
//can delete this store if there is no use of it
bool IsIronManChar() { return IsIronMan; }
bool IsHardcoreChar() { return IsHardcore; }
bool NoMoreLivesLeft() { return TimesDied > 0; }
private:
bool IsIronMan;
bool IsHardcore;
uint32 TimesDied;
bool NeedsDBSave;
uint32 KillerEntry;
};
void PeriodicMonitorPlayerStaysDead(void *p, void *)
{
Player *player = (Player*)p;
if (player->isDead())
return;
IronManHardcoreStore *HCIM = player->GetExtension<IronManHardcoreStore>(OE_PLAYER_IRONMAN_STORE);
//sanity check, should never happen
if (HCIM == NULL)
return;
//suicide if we are allive
if (HCIM->NoMoreLivesLeft())
{
Unit::Kill(player, player);
player->BroadcastMessage("All lives have been consumed. There is no more room for you to walk on this earth");
}
}
bool IsIronManPlayer(Player *p);
bool CheckPlayerCanTurnIronManHardcore(Player *player, int type)
{
//already is ironman
if (IsIronManPlayer(player) == true)
return false;
//if player is in group, disband
if (type == 1 && player->GetGroup())
player->GetGroup()->RemoveMember(player->GetGUID());
//no bags
for (int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++)
{
Item *it = player->GetItemByPos(INVENTORY_SLOT_BAG_0, i);
if (it == NULL)
continue;
if (it->GetTemplate()->Class == ITEM_CLASS_QUIVER || it->GetTemplate()->Class == ITEM_CLASS_PROJECTILE)
continue;
return false;
}
//if we have items in inventory, deny
for (int i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; i++)
{
Item *it = player->GetItemByPos(INVENTORY_SLOT_BAG_0, i);
if (it == NULL)
continue;
if (it->GetTemplate()->Class == ITEM_CLASS_QUIVER || it->GetTemplate()->Class == ITEM_CLASS_PROJECTILE)
continue;
if (it->GetTemplate()->Quality == ITEM_QUALITY_HEIRLOOM)
return false;
if (it->GetTemplate()->RequiredLevel > player->getLevel())
return false;
}
//only new players
if (player->getLevel() > 1)
return false;
//too much time has passed
if (player->GetTotalPlayedTime() > 60)
return false;
// you should not have money on yourself
if (player->GetMoney() != 0)
return false;
return true;
}
void SetIronmanHardcoreMode(Player *player, int type)
{
if (CheckPlayerCanTurnIronManHardcore(player, type) == false )
{
player->BroadcastMessage("Please use a new character for chossing hardcore or ironman modes");
return;
}
IronManHardcoreStore *HCIM = player->GetCreateExtension<IronManHardcoreStore>(OE_PLAYER_IRONMAN_STORE);
if(type == 0)
HCIM->EnableIronMan(player);
else
HCIM->EnableHardcore(player);
}
bool CheckValidClientCommand(const char *cmsg, int32 type, const char * channel);
bool IsIronManPlayer(Player *p)
{
IronManHardcoreStore *HCIM = p->GetExtension<IronManHardcoreStore>(OE_PLAYER_IRONMAN_STORE);
return (HCIM != NULL);
}
bool IsIronmanPlr(Player *p)
{
IronManHardcoreStore *HCIM = p->GetExtension<IronManHardcoreStore>(OE_PLAYER_IRONMAN_STORE);
if (HCIM != NULL) {
if (HCIM->IsIronManChar() && !HCIM->IsHardcoreChar())
return true;
}
return false;
}
bool IsHardcorePlr(Player *p)
{
IronManHardcoreStore *HCIM = p->GetExtension<IronManHardcoreStore>(OE_PLAYER_IRONMAN_STORE);
if (HCIM != NULL) {
if (HCIM->IsHardcoreChar())
return true;
}
return false;
}
class TC_GAME_API IronManHardCoreRegisterScript : public PlayerScript
{
public:
IronManHardCoreRegisterScript() : PlayerScript("IronManHardCoreRegisterScript") {}
void OnLogin(Player* player, bool firstLogin)
{
IronManHardcoreStore *HCIM = player->GetCreateExtension<IronManHardcoreStore>(OE_PLAYER_IRONMAN_STORE);
HCIM->LoadPlayerData(player);
if (HCIM->IsIronManChar() == false)
{
player->DeleteExtension<IronManHardcoreStore>(OE_PLAYER_IRONMAN_STORE);
return;
}
}
// Called when a player logs out.
void OnLogout(Player* player)
{
IronManHardcoreStore *HCIM = player->GetExtension<IronManHardcoreStore>(OE_PLAYER_IRONMAN_STORE);
if (HCIM == NULL)
return;
HCIM->SavePlayerData(player);
}
//hardcore characters can only die once
void OnPlayerKilledByCreature(Creature* killer, Player* killed)
{
//sanity checks
if (killer == NULL || killed == NULL)
return;
//do not register PVP kills
if (killer->GetCharmerOrOwnerGUID() != ObjectGuid::Empty)
return;
//skip arenas and battelgrounds
if (killer->FindMap() && (killer->GetMap()->IsBattleground() || killer->GetMap()->IsBattleArena() || killer->GetMap()->GetId() == 37))
return;
//allow gurubashi arena
if (killer->IsFFAPvP())
return;
//mark him dead if he is a hardcore char
IronManHardcoreStore *HCIM = killed->GetExtension<IronManHardcoreStore>(OE_PLAYER_IRONMAN_STORE);
if (HCIM == NULL)
return;
HCIM->OnDied(killed,killer->GetEntry());
}
void OnDelete(ObjectGuid guid, uint32 accountId)
{
char Query[5000];
sprintf_s(Query, sizeof(Query), "delete from character_IronManHardCore where GUID=%d", (uint32)guid.GetRawValue());
CharacterDatabase.Execute(Query);
}
};
void IronManHardcoreWho(void *p, void *)
{
CP_NAME_QUERY *params = PointerCast(CP_NAME_QUERY, p);
//sanity checks
if (params->Player == NULL)
return;
Player* player = ObjectAccessor::FindConnectedPlayer(ObjectGuid( params->GUID) );
if (player == NULL)
return;
//is this a hardcore char at all ?
IronManHardcoreStore *HCIM = player->GetExtension<IronManHardcoreStore>(OE_PLAYER_IRONMAN_STORE);
if (HCIM == NULL)
return;
std::string Difficulty;
if (HCIM->IsHardcoreChar())
//Difficulty = "|cFFFF0000Hardcore|r";
Difficulty = "Hardcore";
else
//Difficulty = "|cFFFF9900IronMan|r";
Difficulty = "IronMan";
WorldPacket data(SMSG_NAME_QUERY_RESPONSE, (8 + 1 + 1 + 1 + 1 + 1 + 10));
data << ObjectGuid(params->GUID).WriteAsPacked();
data << uint8(0); // name known
data << player->GetName(); // played name
data << Difficulty; // realm name - only set for cross realm interaction (such as Battlegrounds)
data << uint8(player->getRace());
data << uint8(player->getGender()); //sex
data << uint8(player->getClass());
data << uint8(0); // Name is not declined
params->Player->GetSession()->SendPacket(&data);
//do not send real name of the player
params->DenyDefaultParsing = 1;
}
void IParseClientUserCommand(Player* player, uint32 type, std::string& msg)
{
if (CheckValidClientCommand(msg.c_str(), type, NULL) == false)
{
return;
}
#define CHECK_IRONMAN_PREREQUISITS if (player->getLevel() != 1) \
{\
player->BroadcastMessage("You can only use this command on level 1 charcters"); \
return;\
}\
if (player->GetTotalPlayedTime() > 3 * MINUTE)\
{\
player->BroadcastMessage("You can only use this command on a new charcters");\
return;\
}
if (strstr(msg.c_str(), "#csEnableIronMan") == msg.c_str())
{
CHECK_IRONMAN_PREREQUISITS
IronManHardcoreStore *HCIM = player->GetCreateExtension<IronManHardcoreStore>(OE_PLAYER_IRONMAN_STORE);
HCIM->EnableIronMan(player);
}
if (strstr(msg.c_str(), "#csEnableHardcore") == msg.c_str())
{
CHECK_IRONMAN_PREREQUISITS
IronManHardcoreStore *HCIM = player->GetCreateExtension<IronManHardcoreStore>(OE_PLAYER_IRONMAN_STORE);
HCIM->EnableHardcore(player);
}
}
void IOnChatMessageReceived(void *p, void *)
{
CP_CHAT_RECEIVED *params = PointerCast(CP_CHAT_RECEIVED, p);
//check for strings that might be our commands
IParseClientUserCommand(params->SenderPlayer, params->MsgType, *params->Msg);
}
void AddIronManScripts()
{
//CREATE TABLE `character_IronManHardCore` ( `GUID` INT NULL, `IsHardCore` INT NULL, `TimesDied` INT NULL, `KillerEntry` INT NULL );
//ALTER TABLE `character_IronManHardCore` ADD INDEX `GUID` (`GUID`) USING BTREE;
//CREATE UNIQUE INDEX relation ON character_IronManHardCore (GUID);
RegisterCallbackFunction(CALLBACK_TYPE_NAME_QUERY, IronManHardcoreWho, NULL);
RegisterCallbackFunction(CALLBACK_TYPE_CHAT_RECEIVED, IOnChatMessageReceived, NULL);
new IronManHardCoreRegisterScript();
}