Jump to content

[patch] "Pyramid Scheme" style refer a friend


Guest Slurm

Recommended Posts

"Pyramid Scheme" referral. Players get rewards based on the performance of people they refer. Pyramid referrals like this are huge on the internet because people can't resist it, and when the pyramid offers rewards at no cost there is nothing to lose, just refer people and have fun! ^_^

At the moment this is set to give 5% of experience gained and 5% of money gained from drops or vendoring items (and their own redeemed gold) as a bonus to the referring account (no money or experience is lost by the referred player). This would hypothetically come in handy on smaller realms and larger realms to grow and maintain a population. I plan to eventually add a referral points system which could be used to offer rewards such as exclusive items.

Two commands are added as level 0:

.redeemxp

.redeemgold

These will redeem all experience or gold you have accumulated and add them to your character. When players on accounts you have referred gain xp or gold from drops/vendored items it is accumulated until the next player save, at which point it is added to two fields in the account field of your account.

You will have to manually edit your account creation tools to support referrals, or edit the table by hand for testing.

Code for patch from latest rev: (the patch got messy, I'm new to git so i kept committing to master on accident)

diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp
index 8dc9148..8817901 100644
--- a/src/game/Chat.cpp
+++ b/src/game/Chat.cpp
@@ -619,6 +619,9 @@ ChatCommand * ChatHandler::getCommandTable()

    static ChatCommand commandTable[] =
    {
+        { "redeemxp",       SEC_PLAYER,         false,  &ChatHandler::HandleRedeemXPCommand,           "", NULL  },
+        { "redeemgold",     SEC_PLAYER,         false,  &ChatHandler::HandleRedeemMoneyCommand,        "", NULL  },
+
        { "account",        SEC_PLAYER,         true,  NULL,                                           "", accountCommandTable  },
        { "cast",           SEC_ADMINISTRATOR,  false, NULL,                                           "", castCommandTable     },
        { "character",      SEC_GAMEMASTER,     true,  NULL,                                           "", characterCommandTable},
diff --git a/src/game/Chat.h b/src/game/Chat.h
index b82899e..cd3d339 100644
--- a/src/game/Chat.h
+++ b/src/game/Chat.h
@@ -109,6 +109,11 @@ class ChatHandler
        bool HandleAccountSetGmLevelCommand(const char* args);
        bool HandleAccountSetPasswordCommand(const char* args);

+        ///////Referral Commands///////
+        bool HandleRedeemXPCommand(const char* args);
+        bool HandleRedeemMoneyCommand(const char* args);
+        //////Referral Commands///////
+
        bool HandleBanAccountCommand(const char* args);
        bool HandleBanCharacterCommand(const char* args);
        bool HandleBanIPCommand(const char* args);
diff --git a/src/game/ItemHandler.cpp b/src/game/ItemHandler.cpp
index 40cc602..eda4d81 100644
--- a/src/game/ItemHandler.cpp
+++ b/src/game/ItemHandler.cpp
@@ -582,6 +582,8 @@ void WorldSession::HandleSellItemOpcode( WorldPacket & recv_data )
                uint32 money = pProto->SellPrice * count;

                _player->ModifyMoney( money );
+                //Money for referral gained!
+                _player->GainedMoneyForReferral(money);
                _player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS, money);
            }
            else
@@ -627,6 +629,9 @@ void WorldSession::HandleBuybackItem(WorldPacket & recv_data)
        uint8 msg = _player->CanStoreItem( NULL_BAG, NULL_SLOT, dest, pItem, false );
        if( msg == EQUIP_ERR_OK )
        {
+            //Money for referral lost 
+            _player->GainedMoneyForReferral(-(int32)price);
+
            _player->ModifyMoney( -(int32)price );
            _player->RemoveItemFromBuyBackSlot( slot, false );
            _player->ItemAddedQuestCheck( pItem->GetEntry(), pItem->GetCount());
diff --git a/src/game/Level0.cpp b/src/game/Level0.cpp
index e36c147..5c7d27d 100644
--- a/src/game/Level0.cpp
+++ b/src/game/Level0.cpp
@@ -280,3 +280,15 @@ bool ChatHandler::HandleServerMotdCommand(const char* /*args*/)
    PSendSysMessage(LANG_MOTD_CURRENT, sWorld.GetMotd());
    return true;
}
+
+bool ChatHandler::HandleRedeemMoneyCommand(const char *args)
+{
+    m_session->GetPlayer()->RedeemReferralMoney();
+    return true;
+}
+
+bool ChatHandler::HandleRedeemXPCommand(const char *args)
+{
+    m_session->GetPlayer()->RedeemReferralXP();
+    return true;
+}
\\ No newline at end of file
diff --git a/src/game/LootHandler.cpp b/src/game/LootHandler.cpp
index 61fded6..573ea9b 100644
--- a/src/game/LootHandler.cpp
+++ b/src/game/LootHandler.cpp
@@ -242,6 +242,8 @@ void WorldSession::HandleLootMoneyOpcode( WorldPacket & /*recv_data*/ )

            for (std::vector<Player*>::const_iterator i = playersNear.begin(); i != playersNear.end(); ++i)
            {
+                //REFERRAL LOOTS FOR EVERYBODY!!
+                (*i)->GainedMoneyForReferral(money_per_player);
                (*i)->ModifyMoney( money_per_player );
                (*i)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY, money_per_player);
                //Offset surely incorrect, but works
@@ -252,6 +254,7 @@ void WorldSession::HandleLootMoneyOpcode( WorldPacket & /*recv_data*/ )
        }
        else
        {
+            player->GainedMoneyForReferral(pLoot->gold);
            player->ModifyMoney( pLoot->gold );
            player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY, pLoot->gold);
        }
diff --git a/src/game/Player.cpp b/src/game/Player.cpp
index e1be3a8..868fd2e 100644
--- a/src/game/Player.cpp
+++ b/src/game/Player.cpp
@@ -595,6 +595,10 @@ Player::Player (WorldSession *session): Unit(), m_achievementMgr(this), m_reputa

    m_lastFallTime = 0;
    m_lastFallZ = 0;
+    
+    //Pyramid Referral System
+    m_referral_money = 0;
+    m_referral_XP = 0;
}

Player::~Player ()
@@ -2537,6 +2541,9 @@ void Player::GiveXP(uint32 xp, Unit* victim)
    uint32 rested_bonus_xp = victim ? GetXPRestBonus(xp) : 0;

    SendLogXPGain(xp,victim,rested_bonus_xp);
+    
+    //Referral XP
+    m_referral_XP += xp + rested_bonus_xp;

    uint32 curXP = GetUInt32Value(PLAYER_XP);
    uint32 nextLvlXP = GetUInt32Value(PLAYER_NEXT_LEVEL_XP);
@@ -2556,6 +2563,75 @@ void Player::GiveXP(uint32 xp, Unit* victim)
    SetUInt32Value(PLAYER_XP, newXP);
}

+void Player::GainedMoneyForReferral(uint32 money)
+{
+    m_referral_money += money;
+    if(m_referral_money > MAX_MONEY_AMOUNT)
+        m_referral_money = MAX_MONEY_AMOUNT;
+}
+
+void Player::RedeemReferralXP()
+{
+    uint32 currentXP = GetUInt32Value(PLAYER_XP);
+    QueryResult *result = LoginDatabase.PQuery("SELECT referral_xp FROM account WHERE id = '%u'", GetSession()->GetAccountId());
+
+    Field *fields = result->Fetch();
+    uint32 referralXP = fields[0].GetUInt32();
+
+    GiveXP(referralXP, NULL);
+    
+    uint32 excess = 0;
+
+    //if the player goes above maxlvl, the excess xp is refunded
+    if(getLevel() >= sWorld.getConfig(CONFIG_UINT32_MAX_PLAYER_LEVEL))
+        excess = GetUInt32Value(PLAYER_XP);
+
+    LoginDatabase.PExecute("UPDATE account SET referral_xp = '%u' WHERE id = '%u'", excess, GetSession()->GetAccountId());
+}
+
+void Player::RedeemReferralMoney()
+{
+    QueryResult *result = LoginDatabase.PQuery("SELECT referral_money FROM account WHERE id = '%u'", GetSession()->GetAccountId());
+
+    Field *fields = result->Fetch();
+    uint32 referralMoney = fields[0].GetUInt32();
+    
+    uint32 excess = 0;
+
+    //if the player goes above the gold cap excess gold is preserved.
+    if(GetMoney() + referralMoney > MAX_MONEY_AMOUNT)
+        excess = GetMoney() + referralMoney - MAX_MONEY_AMOUNT;
+
+    LoginDatabase.PExecute("UPDATE account SET referral_money = '%u' WHERE id = '%u'", excess, GetSession()->GetAccountId());
+
+    ModifyMoney(referralMoney);
+
+    //Propogates the money upwards just like xp!
+    GainedMoneyForReferral(referralMoney);
+}
+
+void Player::GrantMoneyToReferrer()
+{
+    QueryResult *result = LoginDatabase.PQuery("SELECT referrer FROM account WHERE id = '%u'", GetSession()->GetAccountId());
+
+    Field *fields = result->Fetch();
+    uint32 referrer = fields[0].GetUInt32();
+
+    LoginDatabase.PExecute("UPDATE account SET referral_money = referral_money + '%u' WHERE id = '%u'", m_referral_money / 20, referrer);
+    m_referral_money = 0;
+}
+
+void Player::GrantXpToReferrer()
+{
+    QueryResult *result = LoginDatabase.PQuery("SELECT referrer FROM account WHERE id = '%u'", GetSession()->GetAccountId());
+
+    Field *fields = result->Fetch();
+    uint32 referrer = fields[0].GetUInt32();
+
+    LoginDatabase.PExecute("UPDATE account SET referral_xp = referral_xp + '%u' WHERE id = '%u'", m_referral_XP / 20, referrer);
+    m_referral_XP = 0;
+}
+
// Update player to next level
// Current player experience not update (must be update by caller)
void Player::GiveLevel(uint32 level)
@@ -15013,7 +15089,7 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )
    if(money > MAX_MONEY_AMOUNT)
        money = MAX_MONEY_AMOUNT;
    SetMoney(money);
-
+    
    SetUInt32Value(PLAYER_BYTES, fields[9].GetUInt32());
    SetUInt32Value(PLAYER_BYTES_2, fields[10].GetUInt32());
    SetUInt32Value(PLAYER_BYTES_3, (fields[49].GetUInt16() & 0xFFFE) | fields[5].GetUInt8());
@@ -16659,6 +16735,9 @@ void Player::SaveToDB()
        return;
    }

+    GrantMoneyToReferrer();
+    GrantXpToReferrer();
+
    // first save/honor gain after midnight will also update the player's honor fields
    UpdateHonorFields();

diff --git a/src/game/Player.h b/src/game/Player.h
index ef51208..cbf22e0 100644
--- a/src/game/Player.h
+++ b/src/game/Player.h
@@ -2360,6 +2360,18 @@ class MANGOS_DLL_SPEC Player : public Unit
        void SetTitle(CharTitlesEntry const* title, bool lost = false);

        bool canSeeSpellClickOn(Creature const* creature) const;
+
+        //////////////Pyramid Referral System///////////////
+        uint32 m_referral_XP;
+        uint32 m_referral_money;
+        void GrantXpToReferrer();
+        void GrantMoneyToReferrer();
+        void GainedMoneyForReferral(uint32 money);
+        void RedeemReferralXP();
+        void RedeemReferralMoney();
+        //////////////Pyramid Referral System///////////////
+
+
    protected:

        uint32 m_contestedPvPTimer;
@@ -2556,6 +2568,9 @@ class MANGOS_DLL_SPEC Player : public Unit
        RestType rest_type;
        ////////////////////Rest System/////////////////////

+
+
+
        // Transports
        Transport * m_transport;

Patch for accounts table:

ALTER TABLE account ADD 
   (`referrer` int(11) unsigned DEFAULT NULL COMMENT 'account ID of referrer',
    `referral_xp` bigint(40) unsigned NOT NULL DEFAULT '0',
    `referral_money` bigint(40) unsigned NOT NULL DEFAULT '0')

Example PHP account creation script modified from sticky post (code by Peec) to be relatively secure and compatible with this:

<?php
/*Config*/

$realmd = array(
'db_host'=> 'localhost', //ip of db realm
'db_username' => 'mangos',//realm user
'db_password' => 'mangos',//realm password
'db_name'=> 'realmd',//realm db name
);


///////////////Start script//////////////////

/*
Function name: CHECK FOR SYMBOLS
Description: return TRUE if matches. ( True = OK ) ( False = NOT OK)
*/
function check_for_symbols($string){
$len=strlen($string);
$alowed_chars="abcdefghijklmnopqrstuvwxyzæøåABCDEFGHIJKLMNOPQRSTUVWXYZÆØÅ123456789$%!@.+=-_^&*()#";
for($i=0;$i<$len;$i++)if(!strstr($alowed_chars,$string[$i]))return TRUE;
return FALSE;

}
/*
Function name: OUTPUT USERNAME:PASSWORD AS SHA1 crypt
Description: obious.
*/
function sha_password($user,$pass){
$user = strtoupper($user);
$pass = strtoupper($pass);

return SHA1($user.':'.$pass);
}

if ($_POST['registration'])
{
   /*Connect and Select*/
   $realmd_bc_new_connect = mysql_connect($realmd[db_host],$realmd[db_username],$realmd[db_password]);
   $selectdb = mysql_select_db($realmd[db_name],$realmd_bc_new_connect);

   if (!$realmd_bc_new_connect || !$selectdb)
   {
       echo "Could NOT connect to db.";
       die;
   }

   $username  = mysql_real_escape_string($_POST['username']);
   $password1 = sha_password($username,$_POST['password1']);
   $password2 = sha_password($username,$_POST['password2']);
   $referrer_qry = mysql_query("SELECT id FROM `account` WHERE email='". mysql_real_escape_string($_POST['rafemail'])."'");
   $email     = mysql_real_escape_string($_POST['email']);


   if($username != $_POST['username'])
   {
       echo "ERROR: incorrect username. Please use a valid username.";
       die;
   }

   if($email != $_POST['email'])
   {
       echo "ERROR: invalid email. Please use a valid email.";
       die;
   }

   if(mysql_real_escape_string($_POST['rafemail']) != $_POST['rafemail'])
   {
       echo "ERROR: invalid referral email. Please use a valid referral email or leave referrer email empty.";
       die;
   }
   if($password1 != $password2 )
   {
       echo "Error: passwords do not match.";
       die;
   }

   if(strlen($_POST['password1']) < 6 || strlen($_POST['password1']) > 16)
   {
       echo "Error: password must be between 6 and 16 characters in length.";
       die;
   }

   $referrer = "NULL";
   if($referrer_qry && mysql_num_rows($referrer_qry)>0)
   {
       echo "Referral successful. 
";
       $referrer_row = mysql_fetch_array($referrer_qry);
       $referrer = "'" . $referrer_row[0] . "'";
   }

   $qry_check_username = mysql_query("SELECT username FROM `account` WHERE username='$username'");
   $qry_check_email    = mysql_query("SELECT email FROM `account` WHERE email='$email'");

   if (check_for_symbols($_POST['password1']))
   {
       echo "Error creating account: password contains invalid characters.";
       die;
   }
   if (check_for_symbols($username))
   {
       echo "Error creating account: username contains invalid characters.";
       die;
   }
   if (mysql_num_rows($qry_check_username) != 0)
   {
       echo "Error creating account: username currently in use.";
       die;
   }
   if (mysql_num_rows($qry_check_email) != 0)
   {
       echo "Error with creating account, email currently in use.";
       die;
   }

   if(mysql_query("INSERT INTO account (username,sha_pass_hash,expansion,email,referrer) VALUES
           ('$username','$password1',2,'$email',$referrer)"))
       echo "Account created.";
   else
       echo "Error inserting account into database.";



}
else
{
///////////////Stop script, Start HTML//////////////////
?>


<form action="<?php echo $_SERVER['PHP_SELF'] ?>" method="POST">
Username <input type="text" name="username">


Password <input type="password" name="password1">


Retype Password <input type="password" name="password2">


Email <input type="text" name="email">



If you were referred by a friend put their email below:

<input type="text" name="rafemail" value="<?php echo htmlspecialchars($_GET['raf'])?>">

<input type="submit" name="registration">
</form>


<?php
// Do not remove this;)
}
?>

This is my first patch/mod to the mangos core, and it was quite fun. However, I have not tested this as thoroughly as I would like to because I do not have the resources. If you see anything you don't think is right or notice a bug, I would be very appreciative if you were to post a response.

Link to comment
Share on other sites

+
+void test()
+{
+    uint32 a, b, c;
+    a = b = c = 99;
+    b = a + c;
+
+    return;
+}

Lolwut?

VERY important function you should know!

Actually thanks for pointing that out, I forgot I had written that while I was testing git commands.

Link to comment
Share on other sites

  • 1 month later...
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. Privacy Policy Terms of Use