The goal here is to integrate an external system into Pointshop 2 by using items. Since they are already created we only need to map them to PS2 items. For this example Attachments for Customizable Weaponry 2 are used. CW2 offers a system where players can pick attachments in a menu. Players can only pick attachments that they own.
- Players should be able to buy attachments in Pointshop2
- Players should be given all attachments they own in Pointshop2 so that CW can pick them up
- It should be possible to set the price for the attachments individually
I've created two small utilities for you that are very useful for this script.
- DTextureItemIcon which allows to use texture ids for item/inv icons easily
- Pointshop2.GenerateItemClass to easier bootstrap a new item class
Please see the files below and install them (instructions at the top of each file)
So what we want to do is:
- Generate a lot of items that are very similar (they do nothing at all, they just sit in the users inventory to be picked up by another script)
- Attachments typically don't get removed, removing them is a rare operation
- Once all attachments have been created, there is no point in creating more items for them (i.e. if we have created the Silencer item we won't create a second Silencer item).
- It would be nice to have an in game editor for prices
There are two ways you could go about this:
- Generate a lua defined item for each attachment
- Generate the item classes from lua
I'd go with choice 2) which checks all of the boxes except for b) and d). Removing an item would mean removing it from all inventories first, this is possible through lua but you have to remember to do it.
The idea here is to generate an item class for each attachment (remember: Item Class = Shop Item). Generating a new item class is as easy as this:
-- the method is: GenerateItemClass( className, baseClassName, addonName )
local item = Pointshop2.GenerateItemClass( 'my_custom_class', 'base_pointshop_item', 'CW 2.0 Support' )
item.cwAttachmentId = 'md_bipod'
Since we want all attachments to use material icons and share some properties let's create a new base class. We then need to modify the snippet above to use our new base
addons/ps2-customizable-weaponry/lua/kinv/items/pointshop/sh_base_cw_attachment.lua
ITEM.baseClass = "base_pointshop_item"
ITEM.texture = 0
ITEM.cwAttachmentId = "not set"
-- Returns a Derma Control Name used to create the shop icon in normal mode
function ITEM.static:GetPointshopIconControl( )
return "DPointshopTextureIcon"
end
-- Returns a Derma Control Name used to create the shop icon in lowend mode
function ITEM.static:GetPointshopLowendIconControl( )
return "DPointshopTextureIcon"
end
-- Returns a derma icon that used in the inventory
function ITEM:getIcon( )
self.icon = vgui.Create( "DPointshopTextureInvIcon" )
self.icon:SetItem( self )
return self.icon
end
-- Returns a 4x4 dimensioned icon
function ITEM.static.GetPointshopIconDimensions( )
return Pointshop2.GenerateIconSize( 4, 4 )
end
Then to generate an attachment item we would do:
local bipodItem = Pointshop2.GenerateItemClass( 'my_custom_class', 'base_cw_attachment', 'CW 2.0 Support' )
bipodItem.PrintName = 'Harris Bipod'
bipodItem.Description = 'Decreases recoil by 70%\nGreatly increases hip fire accuracy'
bipodItem.static.Price = {
points = 100,
premiumPoints = 1000
}
bipodItem.cwAttachmentId = 'md_bipod'
We can do this for every attachment now which would be the same as creating a file for each item. That's really annoying and we can do better:
function generateCwClasses( )
for cwAttachmentName, cwAttachmentTable in pairs(CustomizableWeaponry.registeredAttachmentsSKey) do
-- Generate the class
local className = 'cw_' .. cwAttachmentName
local ps2Item = Pointshop2.GenerateItemClass( className, 'base_cw_attachment', 'CW 2.0 Support' )
-- Set the variables
ps2Item.PrintName = cwAttachmentTable.displayName
ps2Item.cwAttachmentName = cwAttachmentName
ps2Item.texture = cwAttachmentTable.displayIcon
-- Put the stats description into a single string
local description = LibK._(cwAttachmentTable.description or {}):chain():pluck("t"):join('\n'):value()
description = description .. '\n\nYou don\'t need to equip this item. Once bought use the CW menu to attach it to your weapon.'
ps2Item.Description = description
KInventory.Items[className] = ps2Item
KLogf(4, "Generated item KInventory.Items.%s for CW2.0 Attachment %s", className, cwAttachmentName )
end
end
if SERVER then
Pointshop2.ModuleItemsLoadedPromise:Then( generateCwClasses )
else
hook.Add( "PS2_ModulesLoaded", "generateClasses", generateCwClasses )
end
Conveniently there is a hook for this in CW that we can use to tell CW that a player owns an attachment (CW20HasAttachment):
hook.Add("CW20HasAttachment", "PS2_HasCwAttachment", function( ply, attachmentName )
-- Make CW recognize attachments in the inventory
-- Return if the player's inventory is not yet loaded
if not ply.PS2_Inventory then return end
-- Go over the player's entire inv
local baseCwAttachment = Pointshop2.GetItemClassByName( 'base_cw_attachment' )
for k, item in pairs( ply.PS2_Inventory:getItems( ) ) do
-- Check if the current item uses the base_cw_attachment base
if instanceOf( baseCwAttachment, item ) then
-- Then check if this is the attachment we're looking for
if item.class.cwAttachmentName == attachmentName then
return true
end
end
end
-- Player doesn't have it, return nothing instead of
-- false to allow other hooks to run as well
return
end )
** Now to disable the default CW2.0 give all attachments on spawn **:
for key, attData in ipairs(CustomizableWeaponry.registeredAttachments) do
game.ConsoleCommand(attData.cvar .. " 0\n")
end
This one should be fairly easy, just create a table with prices and set them in the loop from step 1. You could also get fancy and solve this using module settings to allow the price to be changed from ingame without using a full-blown item creator.
I can write something up for that later.