- Joined
- Sep 3, 2013
- Messages
- 932
- Reaction score
- 254
Hello,
I am re added tutoriel , i have add link for api.
The tutorial is not 100% complete, but I count on you to make it work 100%
Enjoy.
Hey guys, here's a tutorial for a crate system similar to CS:GO The only thing it really needs is the SQL function for it, which i've been working on ALL FUCKING DAY. This system is mainly for newer source, with Terrain V3, i've managed to get it working in an Alpha source, but it needs ALOT of fucking work to work in the older sources, because they switched up how the market works. In the old ones, they separated UIMarket.cpp and FrontEndWarZ.cpp, but in the newer one they said **** it and put it together. WARNING. This is a pretty big tutorial, if your English sucks ass, I recommend you don't do this, because I can't help you if you don't speak English.
Oh, credits to @Valkyrie121 (I think thats his name) because I ripped this from the PDZ Source.
----------------------------
For Newer Sources First
----------------------------
Okay. Step 1. lets get the client out the way.
Search for:
Code:
Below it that function, add
Code:
In the near future, i'll make an animation for rotating through the weapons as they spin.
Anyways, next
Code:
Under that **** add
Code:
Moving on
Code:
Now replace that entire function with this
Code:
Now search for this
Code:
ABOVE IT, Add
Code:
Now search for this
Code:
And above it add
Code:
Basically, that enabled a tab for the crates, you may have to enable a 8th tab in your source if you use guns, or you could disable you guns tab.
Now search for this
Code:
Below that function add
Code:
Now for the definition for it
below
Code:
add
Code:
That SHOULD be it for the client, any compiling errors and i'll update the tutorial. Now we gotta move to the API, and SOME of the database stuff.
[STRIKE]Creds to @GigaToni for some how getting these files, but you need these files here[/STRIKE]
Put the .cs and .aspx files in your API folder, and re-publish it. Then execute the .sql query.
NOW LISTEN
Look in your items_generic, this is where you would put prices for your crates. Make sure the ID's in your new table that was create (Items_CaseData) Basically what this system does is reads "Lootboxes" from items_generics, and casedata is what is contained in each of those, and the percentage if getting it when opening a case. Now last thing is, run this, this creates an SQL function that returns a code 0. This function is not yet done, and i need your guys help to get it working
Code:
And that should be it. Any errors compiling the solution i should be able to fix for ya guys. If anyone knows SQL here, please get that fucking FN_AddItemToUserCase function working. PLEASE YOU NIQQERS.
I am re added tutoriel , i have add link for api.
The tutorial is not 100% complete, but I count on you to make it work 100%
Enjoy.
Hey guys, here's a tutorial for a crate system similar to CS:GO The only thing it really needs is the SQL function for it, which i've been working on ALL FUCKING DAY. This system is mainly for newer source, with Terrain V3, i've managed to get it working in an Alpha source, but it needs ALOT of fucking work to work in the older sources, because they switched up how the market works. In the old ones, they separated UIMarket.cpp and FrontEndWarZ.cpp, but in the newer one they said **** it and put it together. WARNING. This is a pretty big tutorial, if your English sucks ass, I recommend you don't do this, because I can't help you if you don't speak English.
Oh, credits to @Valkyrie121 (I think thats his name) because I ripped this from the PDZ Source.
----------------------------
For Newer Sources First
----------------------------
Okay. Step 1. lets get the client out the way.
Search for:
Code:
Code:
void FrontendWarZ::addStore()
{
#if 0
// add all items to store for test purpose
addAllItemsToStore();
#endif
addStoreToUI(gfxMovie);
}
Code:
Code:
unsigned int WINAPI FrontendWarZ::as_BuyLootBoxThread(void* in_data)
{
r3dThreadAutoInstallCrashHelper crashHelper;
FrontendWarZ* This = (FrontendWarZ*)in_data;
This->DelayServerRequest();
int buyIdx = This->StoreDetectBuyIdx();
if(buyIdx == 0)
{
This->SetAsyncError(-1, gLangMngr.getString("BuyItemFailNoIndex"));
return 0;
}
int apiCode = gUserProfile.ApiLootBoxBuy(This->mStore_BuyItemID, buyIdx);
if(apiCode != 0)
{
This->SetAsyncError(apiCode, gLangMngr.getString("BuyItemFail"));
return 0;
}
return 1;
}
void FrontendWarZ::OnBuyLootBoxSuccess()
{
if(gUserProfile.ProfileData.lastWinID > 0)
{
char winmsg[600];
const WeaponConfig* wc = g_pWeaponArmory->getWeaponConfig(gUserProfile.ProfileData.lastWinID);
const GearConfig* gc = g_pWeaponArmory->getGearConfig(gUserProfile.ProfileData.lastWinID);
const FoodConfig* fc = g_pWeaponArmory->getFoodConfig(gUserProfile.ProfileData.lastWinID);
const BaseItemConfig* ic = g_pWeaponArmory->getFoodConfig(gUserProfile.ProfileData.lastWinID);
SoundSys.PlayAndForget(SoundSys.GetEventIDByPath("Sounds/PandemicZ/Crate/lever8"), r3dPoint3D(0,0,0));
SoundSys.PlayAndForget(SoundSys.GetEventIDByPath("Sounds/PandemicZ/Crate/csgo_ui_crate_open"), r3dPoint3D(0,0,0));
if(wc)
{
sprintf(winmsg, "CONGRATULATIONS\n YOU FOUND A <font color=\"#6496FF\">%s</font>\n IT CAN BE FOUND IN YOUR GLOBAL INVENTORY", wc->m_StoreName);
SoundSys.PlayAndForget(SoundSys.GetEventIDByPath("Sounds/PandemicZ/Crate/item_drop2_uncommon"), r3dPoint3D(0,0,0));
}
else if(gc)
{
sprintf(winmsg, "CONGRATULATIONS\n YOU FOUND A <font color=\"#6496FF\">%s</font>\n IT CAN BE FOUND IN YOUR GLOBAL INVENTORY", gc->m_StoreName);
SoundSys.PlayAndForget(SoundSys.GetEventIDByPath("Sounds/PandemicZ/Crate/item_drop2_uncommon"), r3dPoint3D(0,0,0));
}
else if(fc)
{
sprintf(winmsg, "CONGRATULATIONS\n YOU FOUND A <font color=\"#6496FF\">%s</font>\n IT CAN BE FOUND IN YOUR GLOBAL INVENTORY", fc->m_StoreName);
SoundSys.PlayAndForget(SoundSys.GetEventIDByPath("Sounds/PandemicZ/Crate/item_drop2_uncommon"), r3dPoint3D(0,0,0));
}
else if(ic)
{
sprintf(winmsg, "CONGRATULATIONS\n YOU FOUND A <font color=\"#6496FF\">%s</font>\n IT CAN BE FOUND IN YOUR GLOBAL INVENTORY", ic->m_StoreName);
SoundSys.PlayAndForget(SoundSys.GetEventIDByPath("Sounds/PandemicZ/Crate/item_drop2_uncommon"), r3dPoint3D(0,0,0));
}
else
{
sprintf(winmsg, "OH FIDDLESTICKS\n YOU FOUND <font color=\"#FF6464\">NOTHING</font> IN THAT CASE\n I BETTER LUCK NEXT TIME");
SoundSys.PlayAndForget(SoundSys.GetEventIDByPath("Sounds/PandemicZ/Crate/item_drop2_uncommon"), r3dPoint3D(0,0,0));
}
gfxMovie.Invoke("_root.api.Main.Marketplace.showTransactionsPopup", "");
gfxMovie.Invoke("_root.api.Main.Marketplace.Marketplace.openCase", "");
//setCurrency();
gUserProfile.GetProfile();
Scaleform::GFx::Value var3[1];
var3[0].SetInt(gUserProfile.ProfileData.GamePoints);
gfxMovie.Invoke("_root.api.setGC", var3, 1);
var3[0].SetInt(gUserProfile.ProfileData.GameDollars);
gfxMovie.Invoke("_root.api.setDollars", var3, 1);
/*var3[0].SetInt(gUserProfile.ProfileData.GameCells);
gfxMovie.Invoke("_root.api.setCells", var3, 1);*/
Scaleform::GFx::Value var2[7];
// clear inventory DB
gfxMovie.Invoke("_root.api.clearInventory", NULL, 0);
// add all items
for(uint32_t i=0; i<gUserProfile.ProfileData.NumItems; ++i)
{
var2[0].SetUInt(uint32_t(gUserProfile.ProfileData.Inventory[i].InventoryID));
var2[1].SetUInt(gUserProfile.ProfileData.Inventory[i].itemID);
var2[2].SetNumber(gUserProfile.ProfileData.Inventory[i].quantity);
var2[3].SetNumber(gUserProfile.ProfileData.Inventory[i].Var1);
var2[4].SetNumber(gUserProfile.ProfileData.Inventory[i].Var2);
bool isConsumable = false;
{
const WeaponConfig* wc = g_pWeaponArmory->getWeaponConfig(gUserProfile.ProfileData.Inventory[i].itemID);
if(wc && wc->category == storecat_UsableItem && wc->m_isConsumable)
isConsumable = true;
}
var2[5].SetBoolean(isConsumable);
var2[6].SetString(getAdditionalDescForItem(gUserProfile.ProfileData.Inventory[i].itemID, gUserProfile.ProfileData.Inventory[i].Var1, gUserProfile.ProfileData.Inventory[i].Var2, gUserProfile.ProfileData.Inventory[i].Var3));
gfxMovie.Invoke("_root.api.addInventoryItem", var2, 7);
}
gfxMovie.Invoke("_root.api.buyItemSuccessful", "");
gfxMovie.Invoke("_root.api.hideInfoMsg", "");
/*Scaleform::GFx::Value var[2];
var[0].SetString(winmsg);
var[1].SetBoolean(true);
gfxMovie.Invoke("_root.api.showInfoMsg", var, 2);
/*Scaleform::GFx::Value var[3];
var[0].SetString(winmsg);
var[1].SetString(winmsg);
var[2].SetString(winmsg);
gfxMovie.Invoke("_root.api.Main.Marketplace.setCaseData", var, 3);
gfxMovie.Invoke("_root.api.Main.Marketplace.Marketplace.OpenCase.visible", true);*/
}
else
{
gfxMovie.Invoke("_root.api.buyItemSuccessful", "");
gfxMovie.Invoke("_root.api.hideInfoMsg", "");
Scaleform::GFx::Value var[2];
var[0].SetString("Failed to open case");
var[1].SetBoolean(true);
gfxMovie.Invoke("_root.api.showInfoMsg", var, 2);
}
mStore_BuyItemID = 0;
return;
}
Anyways, next
Code:
Code:
static unsigned int WINAPI as_DeleteCharThread(void* in_data);
void OnDeleteCharSuccess();
Code:
Code:
static unsigned int WINAPI as_BuyLootBoxThread(void* in_data);
void OnBuyLootBoxSuccess();
Code:
Code:
void FrontendWarZ::eventBuyItem(r3dScaleformMovie* pMovie, const Scaleform::GFx::Value* args, unsigned argCount)
Code:
Code:
void FrontendWarZ::eventBuyItem(r3dScaleformMovie* pMovie, const Scaleform::GFx::Value* args, unsigned argCount)
{
mStore_BuyItemID = args[0].GetUInt(); // legsID
mStore_BuyPrice = args[1].GetInt();
mStore_BuyPriceGD = args[2].GetInt();
//mStore_BuyPriceSC = args[3].GetInt();
if(gUserProfile.ProfileData.GameDollars < mStore_BuyPriceGD || gUserProfile.ProfileData.GamePoints < mStore_BuyPrice /*|| gUserProfile.ProfileData.GameCells < mStore_BuyPriceSC*/)
{
Scaleform::GFx::Value var[2];
var[0].SetString(gLangMngr.getString("NotEnougMoneyToBuyItem"));
var[1].SetBoolean(true);
gfxMovie.Invoke("_root.api.showInfoMsg", var, 2);
return;
}
const BaseItemConfig* itemConfig = g_pWeaponArmory->getAccountItemConfig(mStore_BuyItemID);
if(itemConfig && itemConfig->category == storecat_LootBox)
{
if(gUserProfile.haveFreeInventorySlot(false) == false)
{
Scaleform::GFx::Value var[2];
var[0].SetString(gLangMngr.getString("InGameUI_ErrorMsg_NoInventorySpace"));
var[1].SetBoolean(true);
gfxMovie.Invoke("_root.api.showInfoMsg", var, 2);
return;
}
Scaleform::GFx::Value var[2];
var[0].SetString(gLangMngr.getString("OneMomentPlease"));
var[1].SetBoolean(false);
gfxMovie.Invoke("_root.api.showInfoMsg", var, 2);
StartAsyncOperation(&FrontendWarZ::as_BuyLootBoxThread, &FrontendWarZ::OnBuyLootBoxSuccess);
}
else
{
if(gUserProfile.haveFreeInventorySlot(false) == false)
{
Scaleform::GFx::Value var[2];
var[0].SetString(gLangMngr.getString("InGameUI_ErrorMsg_NoInventorySpace"));
var[1].SetBoolean(true);
gfxMovie.Invoke("_root.api.showInfoMsg", var, 2);
return;
}
Scaleform::GFx::Value var[2];
var[0].SetString(gLangMngr.getString("OneMomentPlease"));
var[1].SetBoolean(false);
gfxMovie.Invoke("_root.api.showInfoMsg", var, 2);
StartAsyncOperation(&FrontendWarZ::as_BuyItemThread, &FrontendWarZ::OnBuyItemSuccess);
}
}
Code:
Code:
var[0].SetNumber(storecat_HeroPackage);
Code:
Code:
var[0].SetNumber(storecat_LootBox);
var[1].SetString("SUPPLY DROPS");
var[2].SetNumber(8);
var[3].SetNumber(0);
gfxMovie.Invoke("_root.api.addCategory", var, 4);
Code:
Code:
var[0].SetNumber(0);
var[1].SetString("weapon");
var[2].SetBoolean(false);
var[3].SetBoolean(true);
gfxMovie.Invoke("_root.api.addTabType", var, 4);
Code:
Code:
var[0].SetNumber(8);
var[1].SetString("unknown");
var[2].SetBoolean(true);
var[3].SetBoolean(false);
gfxMovie.Invoke("_root.api.addTabType", var, 4);
Now search for this
Code:
Code:
static void parseCharAttachments(const char* slotData, wiWeaponAttachment& attm)
{
r3d_assert(slotData);
if(*slotData == 0)
{
memset(&attm, 0, sizeof(attm));
return;
}
// should match arguments of ApiCharModifyAttachments
int nargs = sscanf(slotData, "%d %d %d %d %d %d %d %d",
&attm.attachments[0],
&attm.attachments[1],
&attm.attachments[2],
&attm.attachments[3],
&attm.attachments[4],
&attm.attachments[5],
&attm.attachments[6],
&attm.attachments[7]);
if(nargs != 8)
{
r3dOutToLog("Incorrect number of args in attachments %d\n", nargs);
memset(&attm, 0, sizeof(attm));
}
return;
}
Code:
Code:
int CUserProfile::ApiLootBoxBuy(int itemId, int buyIdx)
{
r3d_assert(buyIdx > 0);
CWOBackendReq req(this, "api_MysteryBox.aspx");
req.AddParam("func", "roll");
req.AddParam("ItemID", itemId);
req.AddParam("BuyIdx", buyIdx);
if(!req.Issue())
{
r3dOutToLog("ApiLootBoxBuy FAILED, code: %d\n", req.resultCode_);
return req.resultCode_;
}
int nargs = sscanf(req.bodyStr_, "%d", &ProfileData.lastWinID);
if(nargs != 1)
{
r3dError("wrong answer for ApiMysteryBoxBuy");
return 9;
}
return 0;
}
Now for the definition for it
below
Code:
Code:
void ParseBackpacks(pugi::xml_node& xmlItem);
Code:
Code:
int ApiLootBoxBuy(int itemId, int buyIdx);
[STRIKE]Creds to @GigaToni for some how getting these files, but you need these files here[/STRIKE]
Put the .cs and .aspx files in your API folder, and re-publish it. Then execute the .sql query.
NOW LISTEN
Look in your items_generic, this is where you would put prices for your crates. Make sure the ID's in your new table that was create (Items_CaseData) Basically what this system does is reads "Lootboxes" from items_generics, and casedata is what is contained in each of those, and the percentage if getting it when opening a case. Now last thing is, run this, this creates an SQL function that returns a code 0. This function is not yet done, and i need your guys help to get it working
Code:
Code:
USE [YourDataBaseName]
GO
CREATE PROCEDURE [dbo].[FN_AddItemToUserCase]
@in_CustomerID int,
@in_ItemID int,
@in_ExpDays int
AS
BEGIN
SET NOCOUNT ON;
declare @[I][B][URL="https://forum.ragezone.com/members/31337.html"]inventor[/URL][/B][/I]yID bigint = 0
declare @[I][B][URL="https://forum.ragezone.com/members/876802.html"]Lease[/URL][/B][/I]dUntil datetime
declare @CurDate datetime = GETDATE()
-- check if this is stackable item, if so - get buying stack size.
-- stackable item defined where NumClips>0, Quantity is ClipSize
declare @BuyStackSize int = 1
select @BuyStackSize=ClipSize from Items_Weapons where ItemID=@in_ItemID and NumClips>0
-- see if we already have that item in inventory without modification vars
select @[I][B][URL="https://forum.ragezone.com/members/31337.html"]inventor[/URL][/B][/I]yID=InventoryID, @[I][B][URL="https://forum.ragezone.com/members/876802.html"]Lease[/URL][/B][/I]dUntil=LeasedUntil from UsersInventory
where (CustomerID=@in_CustomerID and CharID=0 and ItemID=@in_ItemID and Var1<0)
if @[I][B][URL="https://forum.ragezone.com/members/31337.html"]inventor[/URL][/B][/I]yID = 0)
begin
INSERT INTO UsersInventory (
CustomerID,
CharID,
ItemID,
LeasedUntil,
Quantity
)
VALUES (
@in_CustomerID,
0,
@in_ItemID,
DATEADD(day, @in_ExpDays, @CurDate),
@BuyStackSize
)
return
end
if @[I][B][URL="https://forum.ragezone.com/members/876802.html"]Lease[/URL][/B][/I]dUntil < @CurDate)
set @[I][B][URL="https://forum.ragezone.com/members/876802.html"]Lease[/URL][/B][/I]dUntil = DATEADD(day, @in_ExpDays, @CurDate)
else
set @[I][B][URL="https://forum.ragezone.com/members/876802.html"]Lease[/URL][/B][/I]dUntil = DATEADD(day, @in_ExpDays, @[I][B][URL="https://forum.ragezone.com/members/876802.html"]Lease[/URL][/B][/I]dUntil)
if @[I][B][URL="https://forum.ragezone.com/members/876802.html"]Lease[/URL][/B][/I]dUntil > '2020-1-1')
set @[I][B][URL="https://forum.ragezone.com/members/876802.html"]Lease[/URL][/B][/I]dUntil = '2020-1-1'
-- all items is stackable by default
UPDATE UsersInventory SET
LeasedUntil @[I][B][URL="https://forum.ragezone.com/members/876802.html"]Lease[/URL][/B][/I]dUntil,
Quantity=(Quantity+@BuyStackSize)
WHERE InventoryID @[I][B][URL="https://forum.ragezone.com/members/31337.html"]inventor[/URL][/B][/I]yID
-- success, not really, just a test
--select 0 as ResultCode
return
END
And that should be it. Any errors compiling the solution i should be able to fix for ya guys. If anyone knows SQL here, please get that fucking FN_AddItemToUserCase function working. PLEASE YOU NIQQERS.
Last edited:

