Guest User

Untitled

a guest
Jan 23rd, 2017
50
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 17.94 KB | None | 0 0
  1. // Blood Money Duels
  2. // Original code by Parranoia from AC-web
  3. // Updated by Faiver from Emudevs
  4. // Edited by Rochet2
  5. // Original thread: http://www.ac-web.org/forums/showthread.php?156980-C-Blood-Money-Duels
  6.  
  7. // Set USE_TOKEN to 1 if you want to have it use tokens in place of gold
  8. #define USE_TOKEN       0
  9. #define TOKEN_ID        29434
  10.  
  11.  
  12. class BloodMoney
  13. {
  14. public:
  15.     // Read write lock and guards
  16.     typedef boost::shared_mutex LockType;
  17.     typedef boost::shared_lock<LockType> ReadGuard;             // Lock for read access: ReadGuard guard(_lock);
  18.     typedef boost::unique_lock<LockType> WriteGuard;            // Lock for write access: WriteGuard guard(_lock);
  19.     typedef boost::upgrade_lock<LockType> RWRead;               // Lock for read access before writing: RWRead read(_lock);
  20.     typedef boost::upgrade_to_unique_lock<LockType> RWWrite;    // Lock for write access before writing: RWWrite write(read);
  21.  
  22.     // Data definitions
  23.     struct MoneyInfo
  24.     {
  25.         MoneyInfo() : challenger(0), amount(0), accepted(false) { }
  26.         uint32 challenger;
  27.         uint32 amount;
  28.         bool accepted;
  29.     };
  30.     typedef std::list<MoneyInfo> MoneyList;
  31.     typedef std::unordered_map<uint32, MoneyList> MoneyListMap;
  32.  
  33.     // Returns a copy or empty list
  34.     MoneyList GetMoneyList(uint32 targetGUID)
  35.     {
  36.         ReadGuard guard(_lock);
  37.         MoneyListMap::const_iterator it = _listMap.find(targetGUID);
  38.         if (it != _listMap.end())
  39.             return it->second;
  40.         return MoneyList();
  41.     }
  42.  
  43.     // Finds a challenge and removes it, then returns the challenge amount. Otherwise returns 0 and does nothing
  44.     uint32 GetAndRemoveChallenge(uint32 targetGUID, uint32 challengerGUID)
  45.     {
  46.         RWRead read(_lock);
  47.         MoneyListMap::iterator it = _listMap.find(targetGUID);
  48.         if (it == _listMap.end())
  49.             return 0;
  50.  
  51.         MoneyList& list = it->second;
  52.         for (MoneyList::iterator itr = list.begin(); itr != list.end(); ++itr)
  53.         {
  54.             if (itr->challenger != challengerGUID)
  55.                 continue;
  56.             if (!itr->accepted)
  57.                 return 0;
  58.  
  59.             uint32 amount = itr->amount;
  60.  
  61.             RWWrite write(read);
  62.             list.erase(itr);
  63.             if (list.empty())
  64.                 _listMap.erase(targetGUID);
  65.  
  66.             return amount;
  67.         }
  68.         return 0;
  69.     }
  70.  
  71.     bool IsChallenged(uint32 targetGUID)
  72.     {
  73.         ReadGuard guard(_lock);
  74.         return _listMap.find(targetGUID) != _listMap.end();
  75.     }
  76.  
  77.     bool HasChallenger(uint32 targetGUID, uint32 challengerGUID)
  78.     {
  79.         ReadGuard guard(_lock);
  80.         MoneyListMap::const_iterator it = _listMap.find(targetGUID);
  81.         if (it == _listMap.end())
  82.             return false;
  83.  
  84.         const MoneyList& list = it->second;
  85.         for (MoneyList::const_iterator itr = list.begin(); itr != list.end(); ++itr)
  86.             if (itr->challenger == challengerGUID)
  87.                 return true;
  88.  
  89.         return false;
  90.     }
  91.  
  92.     bool AddChallenger(uint32 targetGUID, uint32 challengerGUID, uint32 amount)
  93.     {
  94.         MoneyInfo moneyInfo;
  95.         moneyInfo.challenger = challengerGUID;
  96.         moneyInfo.amount = amount;
  97.         moneyInfo.accepted = false;
  98.  
  99.         RWRead read(_lock);
  100.  
  101.         if (HasChallenger(targetGUID, challengerGUID))
  102.             return false;
  103.  
  104.         if (HasChallenger(challengerGUID, targetGUID))
  105.             return false;
  106.  
  107.         RWWrite write(read);
  108.         _listMap[targetGUID].push_back(moneyInfo);
  109.         return true;
  110.     }
  111.  
  112.     bool RemoveChallenger(uint32 targetGUID, uint32 challengerGUID)
  113.     {
  114.         RWRead read(_lock);
  115.         MoneyListMap::iterator it = _listMap.find(targetGUID);
  116.         if (it == _listMap.end())
  117.             return false;
  118.  
  119.         MoneyList &list = it->second;
  120.         for (MoneyList::iterator it = list.begin(); it != list.end(); ++it)
  121.         {
  122.             if (it->challenger != challengerGUID)
  123.                 continue;
  124.  
  125.             RWWrite write(read);
  126.             list.erase(it);
  127.             if (list.empty())
  128.                 _listMap.erase(targetGUID);
  129.             return true;
  130.         }
  131.         return false;
  132.     }
  133.  
  134.     bool AcceptChallenge(uint32 targetGUID, uint32 challengerGUID)
  135.     {
  136.         RWRead read(_lock);
  137.         MoneyListMap::iterator it = _listMap.find(targetGUID);
  138.         if (it == _listMap.end())
  139.             return false;
  140.  
  141.         MoneyList &list = it->second;
  142.         for (MoneyList::iterator itr = list.begin(); itr != list.end(); ++itr)
  143.         {
  144.             if (itr->challenger != challengerGUID)
  145.                 continue;
  146.  
  147.             // Already accepted, internal error
  148.             if (itr->accepted)
  149.                 return false;
  150.  
  151.             RWWrite write(read);
  152.             itr->accepted = true;
  153.             return true;
  154.         }
  155.         return false;
  156.     }
  157.  
  158.     // Used to lock for using GetMap access
  159.     LockType& GetLock()
  160.     {
  161.         return _lock;
  162.     }
  163.  
  164.     // Access map directly, remember to use lock to guard the read and write
  165.     MoneyListMap& GetMap()
  166.     {
  167.         return _listMap;
  168.     }
  169.  
  170. private:
  171.     MoneyListMap _listMap;
  172.     LockType _lock;
  173. };
  174.  
  175. static BloodMoney bloodMoney;
  176.  
  177. class npc_blood_money : public CreatureScript
  178. {
  179. public:
  180.     npc_blood_money() : CreatureScript("npc_blood_money") { }
  181.  
  182.     enum Sender
  183.     {
  184.         SENDER_CLOSE,
  185.         SENDER_CHALLENGE,
  186.         SENDER_ACCEPT,
  187.         SENDER_DECLINE,
  188.     };
  189.  
  190.     bool OnGossipHello(Player* player, Creature* creature) override
  191.     {
  192.         AddGossipItemFor(player, GOSSIP_ICON_BATTLE, "Desafía a un jugador", SENDER_CHALLENGE, 0);
  193.         if (bloodMoney.IsChallenged(player->GetGUID().GetCounter()))
  194.         {
  195.             BloodMoney::MoneyList list = bloodMoney.GetMoneyList(player->GetGUID().GetCounter());
  196.             for (BloodMoney::MoneyList::const_iterator it = list.begin(); it != list.end(); ++it)
  197.             {
  198.                 // Skip accepted entries
  199.                 if (it->accepted)
  200.                     continue;
  201.  
  202.                 if (Player* plr = ObjectAccessor::FindPlayer(ObjectGuid(HighGuid::Player, it->challenger)))
  203.                 {
  204. #if(USE_TOKEN == 1)
  205.                     char msg[100];
  206.                     sprintf(msg, "Acepta %s's Reto de %u tokens", plr->GetName().c_str(), it->amount);
  207.                     AddGossipItemFor(player, GOSSIP_ICON_INTERACT_1, msg, SENDER_ACCEPT, it->challenger);
  208.                     sprintf(msg, "Cancela %s's Reto de %u tokens", plr->GetName().c_str(), it->amount);
  209.                     AddGossipItemFor(player, GOSSIP_ICON_INTERACT_1, msg, SENDER_DECLINE, it->challenger);
  210. #else
  211.                     char msg[100];
  212.                     sprintf(msg, "Acepta %s's Reto de %ug", plr->GetName().c_str(), it->amount);
  213.                     AddGossipItemFor(player, GOSSIP_ICON_INTERACT_1, msg, SENDER_ACCEPT, it->challenger);
  214.                     sprintf(msg, "Cancela %s's Reto de %ug", plr->GetName().c_str(), it->amount);
  215.                     AddGossipItemFor(player, GOSSIP_ICON_INTERACT_1, msg, SENDER_DECLINE, it->challenger);
  216. #endif
  217.                 }
  218.             }
  219.         }
  220.         AddGossipItemFor(player, GOSSIP_ICON_CHAT, "Salir", SENDER_CLOSE, 0);
  221.         SendGossipMenuFor(player, DEFAULT_GOSSIP_MESSAGE, creature->GetGUID());
  222.         return true;
  223.     }
  224.  
  225.     bool OnGossipSelect(Player* player, Creature* creature, uint32 sender, uint32 action)
  226.     {
  227.         ClearGossipMenuFor(Player);
  228.         switch (sender)
  229.         {
  230.             case SENDER_ACCEPT:
  231.                 if (bloodMoney.AcceptChallenge(player->GetGUID().GetCounter(), action))
  232.                 {
  233.                     if (Player* challenger = ObjectAccessor::FindPlayer(ObjectGuid(HighGuid::Player, action)))
  234.                         creature->Whisper(player->GetName() + " ha aceptado su reto!", LANG_UNIVERSAL, challenger, true);
  235.                 }
  236.                 else
  237.                 {
  238.                     player->GetSession()->SendNotification("Error interno, inténtelo de nuevo");
  239.                 }
  240.                 break;
  241.             case SENDER_DECLINE:
  242.                 if (bloodMoney.RemoveChallenger(player->GetGUID().GetCounter(), action))
  243.                 {
  244.                     if (Player* challenger = ObjectAccessor::FindPlayer(ObjectGuid(HighGuid::Player, action)))
  245.                         creature->Whisper(player->GetName() + " ha cancelado su reto!", LANG_UNIVERSAL, challenger, true);
  246.                 }
  247.                 break;
  248.             case SENDER_CHALLENGE:
  249. #if(USE_TOKEN == 1)
  250.                 AddGossipItemExtended(player, GOSSIP_ICON_MONEY_BAG, "Apuesta 5 tokens", GOSSIP_SENDER_MAIN, 5, "", 0, true);
  251.                 AddGossipItemExtended(player, GOSSIP_ICON_MONEY_BAG, "Apuesta 10 tokens", GOSSIP_SENDER_MAIN, 10, "", 0, true);
  252.                 AddGossipItemExtended(player, GOSSIP_ICON_MONEY_BAG, "Apuesta 15 tokens", GOSSIP_SENDER_MAIN, 15, "", 0, true);
  253.                 AddGossipItemExtended(player, GOSSIP_ICON_MONEY_BAG, "Apuesta 25 tokens", GOSSIP_SENDER_MAIN, 25, "", 0, true);
  254.                 AddGossipItemExtended(player, GOSSIP_ICON_MONEY_BAG, "Apuesta 50 tokens", GOSSIP_SENDER_MAIN, 50, "", 0, true);
  255.                 AddGossipItemExtended(player, GOSSIP_ICON_MONEY_BAG, "Apuesta 100 tokens", GOSSIP_SENDER_MAIN, 100, "", 0, true);
  256.                 AddGossipItemExtended(player, GOSSIP_ICON_MONEY_BAG, "Apuesta 150 tokens", GOSSIP_SENDER_MAIN, 150, "", 0, true);
  257.                 AddGossipItemExtended(player, GOSSIP_ICON_MONEY_BAG, "Apuesta 200 tokens", GOSSIP_SENDER_MAIN, 200, "", 0, true);
  258.                 AddGossipItemExtended(player, GOSSIP_ICON_MONEY_BAG, "Apuesta 250 tokens", GOSSIP_SENDER_MAIN, 250, "", 0, true);
  259.                 AddGossipItemExtended(player, GOSSIP_ICON_MONEY_BAG, "Apuesta 500 tokens", GOSSIP_SENDER_MAIN, 500, "", 0, true);
  260. #else
  261.                 AddGossipItemExtended(player, GOSSIP_ICON_MONEY_BAG, "Apuesta 5g", GOSSIP_SENDER_MAIN, 5, "", 5 * GOLD, true);
  262.                 AddGossipItemExtended(player, GOSSIP_ICON_MONEY_BAG, "Apuesta 10g", GOSSIP_SENDER_MAIN, 10, "", 10 * GOLD, true);
  263.                 AddGossipItemExtended(player, GOSSIP_ICON_MONEY_BAG, "Apuesta 15g", GOSSIP_SENDER_MAIN, 15, "", 15 * GOLD, true);
  264.                 AddGossipItemExtended(player, GOSSIP_ICON_MONEY_BAG, "Apuesta 25g", GOSSIP_SENDER_MAIN, 25, "", 25 * GOLD, true);
  265.                 AddGossipItemExtended(player, GOSSIP_ICON_MONEY_BAG, "Apuesta 50g", GOSSIP_SENDER_MAIN, 50, "", 50 * GOLD, true);
  266.                 AddGossipItemExtended(player, GOSSIP_ICON_MONEY_BAG, "Apuesta 100g", GOSSIP_SENDER_MAIN, 100, "", 100 * GOLD, true);
  267.                 AddGossipItemExtended(player, GOSSIP_ICON_MONEY_BAG, "Apuesta 150g", GOSSIP_SENDER_MAIN, 150, "", 150 * GOLD, true);
  268.                 AddGossipItemExtended(player, GOSSIP_ICON_MONEY_BAG, "Apuesta 200g", GOSSIP_SENDER_MAIN, 200, "", 200 * GOLD, true);
  269.                 AddGossipItemExtended(player, GOSSIP_ICON_MONEY_BAG, "Apuesta 250g", GOSSIP_SENDER_MAIN, 250, "", 250 * GOLD, true);
  270.                 AddGossipItemExtended(player, GOSSIP_ICON_MONEY_BAG, "Apuesta 500g", GOSSIP_SENDER_MAIN, 500, "", 500 * GOLD, true);
  271. #endif
  272.                 SendGossipMenuFor(player, DEFAULT_GOSSIP_MESSAGE, creature->GetGUID());
  273.                 return true;
  274.  
  275.             default:
  276.                 CloseGossipMenuFor(player);
  277.                 return true;
  278.         }
  279.  
  280.         OnGossipHello(player, creature);
  281.         return true;
  282.     }
  283.  
  284.     bool OnGossipSelectCode(Player* player, Creature* creature, uint32 sender, uint32 action, const char* code)
  285.     {
  286.         ClearGossipMenuFor(Player);
  287.  
  288.         std::string targetName(code);
  289.         if (player->GetName() == targetName)
  290.         {
  291.             player->GetSession()->SendNotification("No puede ponerse a prueba");
  292.             OnGossipSelect(player, creature, SENDER_CHALLENGE, GOSSIP_ACTION_INFO_DEF);
  293.             return true;
  294.         }
  295.  
  296.         Player* target = ObjectAccessor::FindConnectedPlayerByName(targetName);
  297.         if (!target)
  298.         {
  299.             player->GetSession()->SendNotification("El jugador desafiado no se ha identificado");
  300.             OnGossipSelect(player, creature, SENDER_CHALLENGE, GOSSIP_ACTION_INFO_DEF);
  301.             return true;
  302.         }
  303.  
  304.         if (player->GetGUID() == target->GetGUID())
  305.         {
  306.             player->GetSession()->SendNotification("No puede ponerse a prueba");
  307.             OnGossipSelect(player, creature, SENDER_CHALLENGE, GOSSIP_ACTION_INFO_DEF);
  308.             return true;
  309.         }
  310.  
  311.         if (target->GetZoneId() != player->GetZoneId())
  312.         {
  313.             player->GetSession()->SendNotification("%s no esta dentro de la zona", target->GetName().c_str());
  314.             OnGossipSelect(player, creature, SENDER_CHALLENGE, GOSSIP_ACTION_INFO_DEF);
  315.             return true;
  316.         }
  317.  
  318. #if (USE_TOKEN == 1)
  319.         if (!player->HasItemCount(TOKEN_ID, action))
  320.         {
  321.             player->GetSession()->SendNotification("Usted no tiene suficientes tokens");
  322.             OnGossipSelect(player, creature, SENDER_CHALLENGE, GOSSIP_ACTION_INFO_DEF);
  323.             return true;
  324.         }
  325.  
  326.         if (!target->HasItemCount(TOKEN_ID, action))
  327.         {
  328.             player->GetSession()->SendNotification("%s no tiene suficientes tokens", target->GetName().c_str());
  329.             OnGossipSelect(player, creature, SENDER_CHALLENGE, GOSSIP_ACTION_INFO_DEF);
  330.             return true;
  331.         }
  332. #else
  333.         if (target->GetMoney() < action * GOLD)
  334.         {
  335.             player->GetSession()->SendNotification("%s no tiene suficiente oro", target->GetName().c_str());
  336.             OnGossipSelect(player, creature, SENDER_CHALLENGE, GOSSIP_ACTION_INFO_DEF);
  337.             return true;
  338.         }
  339.  
  340.         if (player->GetMoney() < action * GOLD)
  341.         {
  342.             player->GetSession()->SendNotification("Usted no tiene suficiente oro");
  343.             OnGossipSelect(player, creature, SENDER_CHALLENGE, GOSSIP_ACTION_INFO_DEF);
  344.             return true;
  345.         }
  346. #endif
  347.  
  348.         if (!bloodMoney.AddChallenger(target->GetGUID().GetCounter(), player->GetGUID().GetCounter(), action))
  349.         {
  350.             player->GetSession()->SendNotification("Uno de ustedes ya desafiaron a otro/a");
  351.             OnGossipSelect(player, creature, SENDER_CHALLENGE, GOSSIP_ACTION_INFO_DEF);
  352.             return true;
  353.         }
  354.  
  355.         creature->Whisper(player->GetName() + " ha solicitado un duelo por Oro con usted!", LANG_UNIVERSAL, target, true);
  356.         CloseGossipMenuFor(player);
  357.         return true;
  358.     }
  359. };
  360.  
  361. class BloodMoneyReward : public PlayerScript
  362. {
  363. public:
  364.     BloodMoneyReward() : PlayerScript("BloodMoneyReward") { }
  365.  
  366.     void OnDuelEnd(Player* winner, Player* loser, DuelCompleteType type)
  367.     {
  368.         if (type != DUEL_WON)
  369.             return;
  370.  
  371.         // Loser challenged winner
  372.         uint32 amount = bloodMoney.GetAndRemoveChallenge(winner->GetGUID().GetCounter(), loser->GetGUID().GetCounter());
  373.  
  374.         // Winner challenged loser
  375.         if (!amount)
  376.             amount = bloodMoney.GetAndRemoveChallenge(loser->GetGUID().GetCounter(), winner->GetGUID().GetCounter());
  377.  
  378.         // No challenges
  379.         if (!amount)
  380.             return;
  381.  
  382. #if (USE_TOKEN == 1)
  383.         if (!winner->HasItemCount(TOKEN_ID, amount))
  384.         {
  385.             winner->AddAura(15007, winner); // Apply Rez sickness for possible cheating
  386.             ChatHandler(winner->GetSession()).PSendSysMessage("|cff800C0C[Blood Money] |cffFFFFFFHas ganado resurrección de enfermedad de los posiblemente tratando de abusar del sistema.");
  387.             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.");
  388.         }
  389.         else if (!loser->HasItemCount(TOKEN_ID, amount))
  390.         {
  391.             loser->AddAura(15007, loser);   // Apply Rez sickness for possible cheating
  392.             ChatHandler(winner->GetSession()).PSendSysMessage("|cff800C0C[Blood Money] |cffFFFFFFHas ganado resurrección de enfermedad de los posiblemente tratando de abusar del sistema.");
  393.             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.");
  394.         }
  395.         else
  396.         {
  397.             winner->AddItem(TOKEN_ID, amount);
  398.             loser->DestroyItemCount(TOKEN_ID, amount, true);
  399.             ChatHandler(winner->GetSession()).PSendSysMessage("|cff800C0C[Blood Money] |cffFFFFFFFelicitaciones por ganar %u tokens!", amount);
  400.         }
  401. #else
  402.         int32 money = amount * GOLD;
  403.         if (winner->GetMoney() < money)
  404.         {
  405.             winner->AddAura(15007, winner);         // Apply Rez sickness for possible cheating
  406.             ChatHandler(winner->GetSession()).PSendSysMessage("|cff800C0C[Blood Money] |cffFFFFFFHas ganado resurrección de enfermedad de los posiblemente tratando de abusar del sistema.");
  407.             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.");
  408.         }
  409.         else if (loser->GetMoney() < money)
  410.         {
  411.             loser->AddAura(15007, loser);           // Apply Rez sickness for possible cheating
  412.             ChatHandler(winner->GetSession()).PSendSysMessage("|cff800C0C[Blood Money] |cffFFFFFFSu oponente trató de hacer trampa. Él no tenía suficiente dinero para pagar la apuesta.");
  413.             ChatHandler(loser->GetSession()).PSendSysMessage("|cff800C0C[Blood Money] |cffFFFFFFHas ganado resurrección de enfermedad de los posiblemente tratando de abusar del sistema.");
  414.         }
  415.         else
  416.         {
  417.             winner->ModifyMoney(money);
  418.             loser->ModifyMoney(-money);
  419.             ChatHandler(winner->GetSession()).PSendSysMessage("|cff800C0C[Blood Money] |cffFFFFFFFelicitaciones por ganar %ug!", amount);
  420.         }
  421. #endif
  422.     }
  423. };
  424.  
  425. void AddSC_npc_blood_money()
  426. {
  427.     new BloodMoneyReward();
  428.     new npc_blood_money();
  429. }
Add Comment
Please, Sign In to add comment