Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Blood Money Duels
- // Original code by Parranoia from AC-web
- // Updated by Faiver from Emudevs
- // Edited by Rochet2
- // Original thread: http://www.ac-web.org/forums/showthread.php?156980-C-Blood-Money-Duels
- // Set USE_TOKEN to 1 if you want to have it use tokens in place of gold
- #define USE_TOKEN 0
- #define TOKEN_ID 29434
- class BloodMoney
- {
- public:
- // Read write lock and guards
- typedef boost::shared_mutex LockType;
- typedef boost::shared_lock<LockType> ReadGuard; // Lock for read access: ReadGuard guard(_lock);
- typedef boost::unique_lock<LockType> WriteGuard; // Lock for write access: WriteGuard guard(_lock);
- typedef boost::upgrade_lock<LockType> RWRead; // Lock for read access before writing: RWRead read(_lock);
- typedef boost::upgrade_to_unique_lock<LockType> RWWrite; // Lock for write access before writing: RWWrite write(read);
- // Data definitions
- struct MoneyInfo
- {
- MoneyInfo() : challenger(0), amount(0), accepted(false) { }
- uint32 challenger;
- uint32 amount;
- bool accepted;
- };
- typedef std::list<MoneyInfo> MoneyList;
- typedef std::unordered_map<uint32, MoneyList> MoneyListMap;
- // Returns a copy or empty list
- MoneyList GetMoneyList(uint32 targetGUID)
- {
- ReadGuard guard(_lock);
- MoneyListMap::const_iterator it = _listMap.find(targetGUID);
- if (it != _listMap.end())
- return it->second;
- return MoneyList();
- }
- // Finds a challenge and removes it, then returns the challenge amount. Otherwise returns 0 and does nothing
- uint32 GetAndRemoveChallenge(uint32 targetGUID, uint32 challengerGUID)
- {
- RWRead read(_lock);
- MoneyListMap::iterator it = _listMap.find(targetGUID);
- if (it == _listMap.end())
- return 0;
- MoneyList& list = it->second;
- for (MoneyList::iterator itr = list.begin(); itr != list.end(); ++itr)
- {
- if (itr->challenger != challengerGUID)
- continue;
- if (!itr->accepted)
- return 0;
- uint32 amount = itr->amount;
- RWWrite write(read);
- list.erase(itr);
- if (list.empty())
- _listMap.erase(targetGUID);
- return amount;
- }
- return 0;
- }
- bool IsChallenged(uint32 targetGUID)
- {
- ReadGuard guard(_lock);
- return _listMap.find(targetGUID) != _listMap.end();
- }
- bool HasChallenger(uint32 targetGUID, uint32 challengerGUID)
- {
- ReadGuard guard(_lock);
- MoneyListMap::const_iterator it = _listMap.find(targetGUID);
- if (it == _listMap.end())
- return false;
- const MoneyList& list = it->second;
- for (MoneyList::const_iterator itr = list.begin(); itr != list.end(); ++itr)
- if (itr->challenger == challengerGUID)
- return true;
- return false;
- }
- bool AddChallenger(uint32 targetGUID, uint32 challengerGUID, uint32 amount)
- {
- MoneyInfo moneyInfo;
- moneyInfo.challenger = challengerGUID;
- moneyInfo.amount = amount;
- moneyInfo.accepted = false;
- RWRead read(_lock);
- if (HasChallenger(targetGUID, challengerGUID))
- return false;
- if (HasChallenger(challengerGUID, targetGUID))
- return false;
- RWWrite write(read);
- _listMap[targetGUID].push_back(moneyInfo);
- return true;
- }
- bool RemoveChallenger(uint32 targetGUID, uint32 challengerGUID)
- {
- RWRead read(_lock);
- MoneyListMap::iterator it = _listMap.find(targetGUID);
- if (it == _listMap.end())
- return false;
- MoneyList &list = it->second;
- for (MoneyList::iterator it = list.begin(); it != list.end(); ++it)
- {
- if (it->challenger != challengerGUID)
- continue;
- RWWrite write(read);
- list.erase(it);
- if (list.empty())
- _listMap.erase(targetGUID);
- return true;
- }
- return false;
- }
- bool AcceptChallenge(uint32 targetGUID, uint32 challengerGUID)
- {
- RWRead read(_lock);
- MoneyListMap::iterator it = _listMap.find(targetGUID);
- if (it == _listMap.end())
- return false;
- MoneyList &list = it->second;
- for (MoneyList::iterator itr = list.begin(); itr != list.end(); ++itr)
- {
- if (itr->challenger != challengerGUID)
- continue;
- // Already accepted, internal error
- if (itr->accepted)
- return false;
- RWWrite write(read);
- itr->accepted = true;
- return true;
- }
- return false;
- }
- // Used to lock for using GetMap access
- LockType& GetLock()
- {
- return _lock;
- }
- // Access map directly, remember to use lock to guard the read and write
- MoneyListMap& GetMap()
- {
- return _listMap;
- }
- private:
- MoneyListMap _listMap;
- LockType _lock;
- };
- static BloodMoney bloodMoney;
- class npc_blood_money : public CreatureScript
- {
- public:
- npc_blood_money() : CreatureScript("npc_blood_money") { }
- enum Sender
- {
- SENDER_CLOSE,
- SENDER_CHALLENGE,
- SENDER_ACCEPT,
- SENDER_DECLINE,
- };
- bool OnGossipHello(Player* player, Creature* creature) override
- {
- AddGossipItemFor(player, GOSSIP_ICON_BATTLE, "Desafía a un jugador", SENDER_CHALLENGE, 0);
- if (bloodMoney.IsChallenged(player->GetGUID().GetCounter()))
- {
- BloodMoney::MoneyList list = bloodMoney.GetMoneyList(player->GetGUID().GetCounter());
- for (BloodMoney::MoneyList::const_iterator it = list.begin(); it != list.end(); ++it)
- {
- // Skip accepted entries
- if (it->accepted)
- continue;
- if (Player* plr = ObjectAccessor::FindPlayer(ObjectGuid(HighGuid::Player, it->challenger)))
- {
- #if(USE_TOKEN == 1)
- char msg[100];
- sprintf(msg, "Acepta %s's Reto de %u tokens", plr->GetName().c_str(), it->amount);
- AddGossipItemFor(player, GOSSIP_ICON_INTERACT_1, msg, SENDER_ACCEPT, it->challenger);
- sprintf(msg, "Cancela %s's Reto de %u tokens", plr->GetName().c_str(), it->amount);
- AddGossipItemFor(player, GOSSIP_ICON_INTERACT_1, msg, SENDER_DECLINE, it->challenger);
- #else
- char msg[100];
- sprintf(msg, "Acepta %s's Reto de %ug", plr->GetName().c_str(), it->amount);
- AddGossipItemFor(player, GOSSIP_ICON_INTERACT_1, msg, SENDER_ACCEPT, it->challenger);
- sprintf(msg, "Cancela %s's Reto de %ug", plr->GetName().c_str(), it->amount);
- AddGossipItemFor(player, GOSSIP_ICON_INTERACT_1, msg, SENDER_DECLINE, it->challenger);
- #endif
- }
- }
- }
- AddGossipItemFor(player, GOSSIP_ICON_CHAT, "Salir", SENDER_CLOSE, 0);
- SendGossipMenuFor(player, DEFAULT_GOSSIP_MESSAGE, creature->GetGUID());
- return true;
- }
- bool OnGossipSelect(Player* player, Creature* creature, uint32 sender, uint32 action)
- {
- ClearGossipMenuFor(Player);
- switch (sender)
- {
- case SENDER_ACCEPT:
- if (bloodMoney.AcceptChallenge(player->GetGUID().GetCounter(), action))
- {
- if (Player* challenger = ObjectAccessor::FindPlayer(ObjectGuid(HighGuid::Player, action)))
- creature->Whisper(player->GetName() + " ha aceptado su reto!", LANG_UNIVERSAL, challenger, true);
- }
- else
- {
- player->GetSession()->SendNotification("Error interno, inténtelo de nuevo");
- }
- break;
- case SENDER_DECLINE:
- if (bloodMoney.RemoveChallenger(player->GetGUID().GetCounter(), action))
- {
- if (Player* challenger = ObjectAccessor::FindPlayer(ObjectGuid(HighGuid::Player, action)))
- creature->Whisper(player->GetName() + " ha cancelado su reto!", LANG_UNIVERSAL, challenger, true);
- }
- break;
- case SENDER_CHALLENGE:
- #if(USE_TOKEN == 1)
- AddGossipItemExtended(player, GOSSIP_ICON_MONEY_BAG, "Apuesta 5 tokens", GOSSIP_SENDER_MAIN, 5, "", 0, true);
- AddGossipItemExtended(player, GOSSIP_ICON_MONEY_BAG, "Apuesta 10 tokens", GOSSIP_SENDER_MAIN, 10, "", 0, true);
- AddGossipItemExtended(player, GOSSIP_ICON_MONEY_BAG, "Apuesta 15 tokens", GOSSIP_SENDER_MAIN, 15, "", 0, true);
- AddGossipItemExtended(player, GOSSIP_ICON_MONEY_BAG, "Apuesta 25 tokens", GOSSIP_SENDER_MAIN, 25, "", 0, true);
- AddGossipItemExtended(player, GOSSIP_ICON_MONEY_BAG, "Apuesta 50 tokens", GOSSIP_SENDER_MAIN, 50, "", 0, true);
- AddGossipItemExtended(player, GOSSIP_ICON_MONEY_BAG, "Apuesta 100 tokens", GOSSIP_SENDER_MAIN, 100, "", 0, true);
- AddGossipItemExtended(player, GOSSIP_ICON_MONEY_BAG, "Apuesta 150 tokens", GOSSIP_SENDER_MAIN, 150, "", 0, true);
- AddGossipItemExtended(player, GOSSIP_ICON_MONEY_BAG, "Apuesta 200 tokens", GOSSIP_SENDER_MAIN, 200, "", 0, true);
- AddGossipItemExtended(player, GOSSIP_ICON_MONEY_BAG, "Apuesta 250 tokens", GOSSIP_SENDER_MAIN, 250, "", 0, true);
- AddGossipItemExtended(player, GOSSIP_ICON_MONEY_BAG, "Apuesta 500 tokens", GOSSIP_SENDER_MAIN, 500, "", 0, true);
- #else
- AddGossipItemExtended(player, GOSSIP_ICON_MONEY_BAG, "Apuesta 5g", GOSSIP_SENDER_MAIN, 5, "", 5 * GOLD, true);
- AddGossipItemExtended(player, GOSSIP_ICON_MONEY_BAG, "Apuesta 10g", GOSSIP_SENDER_MAIN, 10, "", 10 * GOLD, true);
- AddGossipItemExtended(player, GOSSIP_ICON_MONEY_BAG, "Apuesta 15g", GOSSIP_SENDER_MAIN, 15, "", 15 * GOLD, true);
- AddGossipItemExtended(player, GOSSIP_ICON_MONEY_BAG, "Apuesta 25g", GOSSIP_SENDER_MAIN, 25, "", 25 * GOLD, true);
- AddGossipItemExtended(player, GOSSIP_ICON_MONEY_BAG, "Apuesta 50g", GOSSIP_SENDER_MAIN, 50, "", 50 * GOLD, true);
- AddGossipItemExtended(player, GOSSIP_ICON_MONEY_BAG, "Apuesta 100g", GOSSIP_SENDER_MAIN, 100, "", 100 * GOLD, true);
- AddGossipItemExtended(player, GOSSIP_ICON_MONEY_BAG, "Apuesta 150g", GOSSIP_SENDER_MAIN, 150, "", 150 * GOLD, true);
- AddGossipItemExtended(player, GOSSIP_ICON_MONEY_BAG, "Apuesta 200g", GOSSIP_SENDER_MAIN, 200, "", 200 * GOLD, true);
- AddGossipItemExtended(player, GOSSIP_ICON_MONEY_BAG, "Apuesta 250g", GOSSIP_SENDER_MAIN, 250, "", 250 * GOLD, true);
- AddGossipItemExtended(player, GOSSIP_ICON_MONEY_BAG, "Apuesta 500g", GOSSIP_SENDER_MAIN, 500, "", 500 * GOLD, true);
- #endif
- SendGossipMenuFor(player, DEFAULT_GOSSIP_MESSAGE, creature->GetGUID());
- return true;
- default:
- CloseGossipMenuFor(player);
- return true;
- }
- OnGossipHello(player, creature);
- return true;
- }
- bool OnGossipSelectCode(Player* player, Creature* creature, uint32 sender, uint32 action, const char* code)
- {
- ClearGossipMenuFor(Player);
- std::string targetName(code);
- if (player->GetName() == targetName)
- {
- player->GetSession()->SendNotification("No puede ponerse a prueba");
- OnGossipSelect(player, creature, SENDER_CHALLENGE, GOSSIP_ACTION_INFO_DEF);
- return true;
- }
- Player* target = ObjectAccessor::FindConnectedPlayerByName(targetName);
- if (!target)
- {
- player->GetSession()->SendNotification("El jugador desafiado no se ha identificado");
- OnGossipSelect(player, creature, SENDER_CHALLENGE, GOSSIP_ACTION_INFO_DEF);
- return true;
- }
- if (player->GetGUID() == target->GetGUID())
- {
- player->GetSession()->SendNotification("No puede ponerse a prueba");
- OnGossipSelect(player, creature, SENDER_CHALLENGE, GOSSIP_ACTION_INFO_DEF);
- return true;
- }
- if (target->GetZoneId() != player->GetZoneId())
- {
- player->GetSession()->SendNotification("%s no esta dentro de la zona", target->GetName().c_str());
- OnGossipSelect(player, creature, SENDER_CHALLENGE, GOSSIP_ACTION_INFO_DEF);
- return true;
- }
- #if (USE_TOKEN == 1)
- if (!player->HasItemCount(TOKEN_ID, action))
- {
- player->GetSession()->SendNotification("Usted no tiene suficientes tokens");
- OnGossipSelect(player, creature, SENDER_CHALLENGE, GOSSIP_ACTION_INFO_DEF);
- return true;
- }
- if (!target->HasItemCount(TOKEN_ID, action))
- {
- player->GetSession()->SendNotification("%s no tiene suficientes tokens", target->GetName().c_str());
- OnGossipSelect(player, creature, SENDER_CHALLENGE, GOSSIP_ACTION_INFO_DEF);
- return true;
- }
- #else
- if (target->GetMoney() < action * GOLD)
- {
- player->GetSession()->SendNotification("%s no tiene suficiente oro", target->GetName().c_str());
- OnGossipSelect(player, creature, SENDER_CHALLENGE, GOSSIP_ACTION_INFO_DEF);
- return true;
- }
- if (player->GetMoney() < action * GOLD)
- {
- player->GetSession()->SendNotification("Usted no tiene suficiente oro");
- OnGossipSelect(player, creature, SENDER_CHALLENGE, GOSSIP_ACTION_INFO_DEF);
- return true;
- }
- #endif
- if (!bloodMoney.AddChallenger(target->GetGUID().GetCounter(), player->GetGUID().GetCounter(), action))
- {
- player->GetSession()->SendNotification("Uno de ustedes ya desafiaron a otro/a");
- OnGossipSelect(player, creature, SENDER_CHALLENGE, GOSSIP_ACTION_INFO_DEF);
- return true;
- }
- creature->Whisper(player->GetName() + " ha solicitado un duelo por Oro con usted!", LANG_UNIVERSAL, target, true);
- CloseGossipMenuFor(player);
- return true;
- }
- };
- class BloodMoneyReward : public PlayerScript
- {
- public:
- BloodMoneyReward() : PlayerScript("BloodMoneyReward") { }
- void OnDuelEnd(Player* winner, Player* loser, DuelCompleteType type)
- {
- if (type != DUEL_WON)
- return;
- // Loser challenged winner
- uint32 amount = bloodMoney.GetAndRemoveChallenge(winner->GetGUID().GetCounter(), loser->GetGUID().GetCounter());
- // Winner challenged loser
- if (!amount)
- amount = bloodMoney.GetAndRemoveChallenge(loser->GetGUID().GetCounter(), winner->GetGUID().GetCounter());
- // No challenges
- if (!amount)
- return;
- #if (USE_TOKEN == 1)
- if (!winner->HasItemCount(TOKEN_ID, amount))
- {
- winner->AddAura(15007, winner); // Apply Rez sickness for possible cheating
- ChatHandler(winner->GetSession()).PSendSysMessage("|cff800C0C[Blood Money] |cffFFFFFFHas ganado resurrección de enfermedad de los posiblemente tratando de abusar del sistema.");
- ChatHandler(loser->GetSession()).PSendSysMessage("|cff800C0C[Blood Money] |cffFFFFFFSu oponente trató de hacer trampa. No se preocupe que no pierde ninguna tokens a causa de esto.");
- }
- else if (!loser->HasItemCount(TOKEN_ID, amount))
- {
- loser->AddAura(15007, loser); // Apply Rez sickness for possible cheating
- ChatHandler(winner->GetSession()).PSendSysMessage("|cff800C0C[Blood Money] |cffFFFFFFHas ganado resurrección de enfermedad de los posiblemente tratando de abusar del sistema.");
- ChatHandler(loser->GetSession()).PSendSysMessage("|cff800C0C[Blood Money] |cffFFFFFFSu oponente trató de hacer trampa. No se preocupe que no pierde ninguna tokens a causa de esto.");
- }
- else
- {
- winner->AddItem(TOKEN_ID, amount);
- loser->DestroyItemCount(TOKEN_ID, amount, true);
- ChatHandler(winner->GetSession()).PSendSysMessage("|cff800C0C[Blood Money] |cffFFFFFFFelicitaciones por ganar %u tokens!", amount);
- }
- #else
- int32 money = amount * GOLD;
- if (winner->GetMoney() < money)
- {
- winner->AddAura(15007, winner); // Apply Rez sickness for possible cheating
- ChatHandler(winner->GetSession()).PSendSysMessage("|cff800C0C[Blood Money] |cffFFFFFFHas ganado resurrección de enfermedad de los posiblemente tratando de abusar del sistema.");
- ChatHandler(loser->GetSession()).PSendSysMessage("|cff800C0C[Blood Money] |cffFFFFFFSu oponente trató de hacer trampa. No se preocupe que no se pierde ningún oro a causa de esto.");
- }
- else if (loser->GetMoney() < money)
- {
- loser->AddAura(15007, loser); // Apply Rez sickness for possible cheating
- ChatHandler(winner->GetSession()).PSendSysMessage("|cff800C0C[Blood Money] |cffFFFFFFSu oponente trató de hacer trampa. Él no tenía suficiente dinero para pagar la apuesta.");
- ChatHandler(loser->GetSession()).PSendSysMessage("|cff800C0C[Blood Money] |cffFFFFFFHas ganado resurrección de enfermedad de los posiblemente tratando de abusar del sistema.");
- }
- else
- {
- winner->ModifyMoney(money);
- loser->ModifyMoney(-money);
- ChatHandler(winner->GetSession()).PSendSysMessage("|cff800C0C[Blood Money] |cffFFFFFFFelicitaciones por ganar %ug!", amount);
- }
- #endif
- }
- };
- void AddSC_npc_blood_money()
- {
- new BloodMoneyReward();
- new npc_blood_money();
- }
Add Comment
Please, Sign In to add comment