rbxIdleWeapon/src/ServerStorage/Proxy/EquipmentProxy.luau

372 lines
15 KiB
Plaintext

-- 装备代理
local EquipmentProxy = {}
--> Services
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerStorage = game:GetService("ServerStorage")
--> Variables
local Utils = require(ReplicatedStorage.Tools.Utils)
local ArchiveProxy = require(ServerStorage.Proxy.ArchiveProxy)
local PlayerInfoProxy = require(ServerStorage.Proxy.PlayerInfoProxy)
local PlayerFightProxy = require(ServerStorage.Proxy.PlayerFightProxy)
--> Json
local JsonEquipment = require(ReplicatedStorage.Json.Equipment)
local JsonAttributes = require(ReplicatedStorage.Json.Attributes)
local JsonExAttributes = require(ReplicatedStorage.Json.ExAttributes)
local JsonParam = require(ReplicatedStorage.Json.Param)
--> Events
local RE_PlayerTip = ReplicatedStorage.Events.RE_PlayerTip
local RE_WearEquipment = ReplicatedStorage.Events.RE_WearEquipment
--> Constants
local STORE_NAME = "Equipment"
--------------------------------------------------------------------------------
-- 获取装备文件夹
local function GetPlayerEquipmentFolder(Player: Player)
local pData = Utils:GetPlayerDataFolder(Player)
if not pData then return end
local EquipmentFolder = pData:FindFirstChild("Equipment")
return EquipmentFolder
end
-- 计算词条等级加成上限
local function GetEntryLvBonus(PlayerLv: number, BonusData: table)
local bonus = math.floor(PlayerLv / BonusData[1]) * BonusData[2]
return math.min(bonus, BonusData[3])
end
-- 改变装备数据
local function ChangeValue(Player: Player, EquipmentUniqueId: number, KeyName: string, Value: any)
if not Player or not EquipmentUniqueId or not KeyName then warn("EquipmentProxy ChangeValue", Player.UserId, EquipmentUniqueId, KeyName, Value) return end
local ValueInstance = GetPlayerEquipmentFolder(Player):FindFirstChild(EquipmentUniqueId)
if not ValueInstance then warn("ValueInstance not found", KeyName) return end
ArchiveProxy.pData[Player.UserId][EquipmentUniqueId][KeyName] = Value
ValueInstance:SetAttribute(KeyName, Value)
end
--------------------------------------------------------------------------------
-- 初始化玩家
function EquipmentProxy:InitPlayer(Player: Player)
local pData = Utils:GetPlayerDataFolder(Player)
if not pData then return end
Utils:CreateFolder("Equipment", pData)
-- 新玩家数据初始化
if not ArchiveProxy.pData[Player.UserId][STORE_NAME] then
ArchiveProxy.pData[Player.UserId][STORE_NAME] = {}
end
-- 初始化装备
for uniqueId, EquipmentData in ArchiveProxy.pData[Player.UserId][STORE_NAME] do
local config = Utils:CreateDataInstance(Player, uniqueId, EquipmentData, GetPlayerEquipmentFolder(Player))
end
end
-- 一些特殊记录或者不用记录的Key
local EXCEPT_KEYS = { "id", "orgId", "name", "attributes"}
-- 添加装备到背包
function EquipmentProxy:AddEquipment(Player: Player, EquipmentId: number)
local pData = Utils:GetPlayerDataFolder(Player)
if not pData then return end
local EquipmentData = Utils:GetIdDataFromJson(JsonEquipment, EquipmentId)
if not EquipmentData then return end
local UniqueId = Utils:GenUniqueId(ArchiveProxy.pData[Player.UserId][STORE_NAME])
-- 配置表内容
local ResultData = {}
for key, value in pairs(EquipmentData) do
if not table.find(EXCEPT_KEYS, key) then
ResultData[key] = value
end
end
ResultData.id = UniqueId
ResultData.orgId = EquipmentId
-- 到时候记录穿戴槽位
ResultData.wearing = 0
-- 随机生成总变量
local rng = Random.new()
local PlayerLevel = PlayerInfoProxy:GetPlayerLevel(Player)
-- TODO: 之后这里可能根据等级限制权重
-- 随机生成品质
local qualityWeightTable = {
[1] = 90,
[2] = 70,
[3] = 50,
[4] = 30,
[5] = 10,
[6] = 5,
}
local quality = Utils:GetRandomWeightIndex(qualityWeightTable)
local qualityParam = Utils:GetIdDataFromJson(JsonParam, 1).intArray
ResultData.quality = quality
-- 生成装备基础词条(固定的)
ResultData.attributes = {}
for i = 1, #EquipmentData.attributes, 3 do
local AttributeData = Utils:GetIdDataFromJson(JsonAttributes, EquipmentData.attributes[i])
local baseLvValue = EquipmentData.attributes[i + 1] + EquipmentData.attributes[i + 2] * (PlayerLevel - 1)
local qualityEffectValue = math.floor(baseLvValue * (qualityParam[quality] / 100))
ResultData.attributes[AttributeData.effectAttribute] = qualityEffectValue
end
-- TODO: 其他随机词条内容添加在下面
-- 随机生成额外属性数量
local maxExAttributeNumber = PlayerInfoProxy:GetPlayerInfo(Player).exAttributeNumber or 0
local exAttributeNumber = rng:NextInteger(0, maxExAttributeNumber)
ResultData.maxExAttributeNumber = exAttributeNumber
ResultData.exAttributes = {}
if exAttributeNumber > 0 then
local spawnExAttributesId = {}
for i = 1, exAttributeNumber do
local newExAttributeId = Utils:GetRandomIdFromJsonWithType(JsonExAttributes, 1, spawnExAttributesId)
table.insert(spawnExAttributesId, newExAttributeId)
local ExAttributeData = Utils:GetIdDataFromJson(JsonExAttributes, newExAttributeId)
local minValue = ExAttributeData.randomValue[1]
local maxValue = ExAttributeData.randomValue[2] + GetEntryLvBonus(PlayerLevel, ExAttributeData.bonus)
local randomExAttributeValue = rng:NextInteger(minValue, maxValue)
local AttributeData = Utils:GetIdDataFromJson(JsonAttributes, newExAttributeId)
ResultData.exAttributes[AttributeData.name] = randomExAttributeValue
end
end
-- 随机生成元素属性数量(暂时跟额外属性相同,之后可以改逻辑)
local maxElementNumber = PlayerInfoProxy:GetPlayerInfo(Player).elementNumber or 0
local elementNumber = rng:NextInteger(0, maxElementNumber)
ResultData.maxElementNumber = elementNumber
ResultData.elements = {}
if elementNumber > 0 then
local spawnElementsId = {}
for i = 1, elementNumber do
local newElementAttributeId = Utils:GetRandomIdFromJsonWithType(JsonExAttributes, 1, spawnElementsId)
table.insert(spawnElementsId, newElementAttributeId)
local ElementAttributeData = Utils:GetIdDataFromJson(JsonExAttributes, newElementAttributeId)
local minValue = ElementAttributeData.randomValue[1]
local maxValue = ElementAttributeData.randomValue[2] + GetEntryLvBonus(PlayerLevel, ElementAttributeData.bonus)
local randomElementAttributeValue = rng:NextInteger(minValue, maxValue)
local AttributeData = Utils:GetIdDataFromJson(JsonAttributes, newElementAttributeId)
ResultData.elements[AttributeData.name] = randomElementAttributeValue
end
end
-- 随机生成元素抗性数量
local maxElementDefNumber = PlayerInfoProxy:GetPlayerInfo(Player).elementDefNumber or 0
local elementDefNumber = rng:NextInteger(0, maxElementDefNumber)
ResultData.maxElementDefNumber = elementDefNumber
ResultData.elementDef = {}
if elementDefNumber > 0 then
local spawnElementDefId = {}
for i = 1, elementDefNumber do
local newElementDefId = Utils:GetRandomIdFromJsonWithType(JsonExAttributes, 1, spawnElementDefId)
table.insert(spawnElementDefId, newElementDefId)
local ElementDefAttributeData = Utils:GetIdDataFromJson(JsonExAttributes, newElementDefId)
local minValue = ElementDefAttributeData.randomValue[1]
local maxValue = ElementDefAttributeData.randomValue[2] + GetEntryLvBonus(PlayerLevel, ElementDefAttributeData.bonus)
local randomElementDefAttributeValue = rng:NextInteger(minValue, maxValue)
local AttributeData = Utils:GetIdDataFromJson(JsonAttributes, newElementDefId)
ResultData.elementDef[AttributeData.name] = randomElementDefAttributeValue
end
end
-- 随机生成技能槽位数量
local AbilityProxy = require(ServerStorage.Proxy.AbilityProxy)
local maxAbilityNumber = PlayerInfoProxy:GetPlayerInfo(Player).abilityNumber or 0
local abilityNumber = rng:NextInteger(0, maxAbilityNumber)
ResultData.maxAbilityNumber = abilityNumber
if abilityNumber > 0 then
local spawnAbilitiesId = {}
for i = 1, abilityNumber do
local newAbilityId = AbilityProxy:GetRandomAbilityId(spawnAbilitiesId)
table.insert(spawnAbilitiesId, newAbilityId)
local newAbilityData, newAbilityInstance = AbilityProxy:AddAbility(Player, newAbilityId)
AbilityProxy:WearAbility(Player, newAbilityData.id, UniqueId)
end
end
-- 随机生成宝石数量
local GemProxy = require(ServerStorage.Proxy.GemProxy)
local maxGemNumber = PlayerInfoProxy:GetPlayerInfo(Player).gemNumber or 0
local gemNumber = rng:NextInteger(0, maxGemNumber)
ResultData.maxGemNumber = gemNumber
if gemNumber > 0 then
local spawnGemsId = {}
for i = 1, gemNumber do
local newGemId = GemProxy:GetRandomGemId(spawnGemsId)
table.insert(spawnGemsId, newGemId)
local newGemData, newGemInstance = GemProxy:AddGem(Player, newGemId)
GemProxy:WearGem(Player, newGemData.id, UniqueId)
end
end
------------------------------------------------------------
ArchiveProxy.pData[Player.UserId][STORE_NAME][UniqueId] = ResultData
print(ArchiveProxy.pData[Player.UserId][STORE_NAME])
Utils:CreateDataInstance(Player, UniqueId, ResultData, GetPlayerEquipmentFolder(Player))
-- 添加图鉴记录
local BookProxy = require(ServerStorage.Proxy.BookProxy)
BookProxy:AddBook(Player, EquipmentId, UniqueId)
end
-- 回收装备
function EquipmentProxy:RecycleEquipment(Player: Player, EquipmentId: number)
local pData = Utils:GetPlayerDataFolder(Player)
if not pData then return end
local EquipmentData = ArchiveProxy.pData[Player.UserId][STORE_NAME][EquipmentId]
if not EquipmentData then return end
-- 根据对应功能模块进行对应回收
local AbilityProxy = require(ServerStorage.Proxy.AbilityProxy)
AbilityProxy:RecycleAbility(Player, EquipmentData.id)
local GemProxy = require(ServerStorage.Proxy.GemProxy)
GemProxy:RecycleGem(Player, EquipmentData.id)
-- 回收装备返回金币
-- TODO:处理关卡金币产出加成和词条加成
PlayerInfoProxy:ChangeItem(Player, 1, EquipmentData.recycle)
ArchiveProxy.pData[Player.UserId][EquipmentId] = nil
local EquipmentInstance = GetPlayerEquipmentFolder(Player):FindFirstChild(EquipmentId)
if EquipmentInstance then
EquipmentInstance:Destroy()
end
end
-- 穿戴装备
function EquipmentProxy:WearEquipment(Player: Player, EquipmentId: number, Slot: number)
local pData = Utils:GetPlayerDataFolder(Player)
if not pData then return end
-- TODO :穿戴装备时再生成模型
-- 查看槽位数量是否超出
local PlayerInfoData = PlayerInfoProxy:GetPlayerInfo(Player)
-- 没升级是没有键值对的,所以做了个括号简单判断
if Slot > (PlayerInfoData.AttributesUpgrade.wearingNumber or 1) then
RE_PlayerTip:FireClient(Player, '穿戴装备槽位超出')
return
end
-- 查看该槽位是否穿戴装备,穿戴就返回
for _, EquipmentData in ArchiveProxy.pData[Player.UserId][STORE_NAME] do
if EquipmentData.wearing == Slot then
RE_PlayerTip:FireClient(Player, '该槽位已穿戴装备')
return
end
end
-- 穿戴装备
local EquipmentData = ArchiveProxy.pData[Player.UserId][STORE_NAME][EquipmentId]
if not EquipmentData then return end
ChangeValue(Player, EquipmentId, "wearing", Slot)
-- 更新玩家数据
PlayerFightProxy:UpdatePlayerFightData(Player)
end
-- 卸下装备
function EquipmentProxy:UnwearEquipment(Player: Player, EquipmentId: number)
local pData = Utils:GetPlayerDataFolder(Player)
if not pData then return end
-- TODO :卸下装备时再关闭模型
-- 卸下装备
local EquipmentData = ArchiveProxy.pData[Player.UserId][STORE_NAME][EquipmentId]
if not EquipmentData then return end
ChangeValue(Player, EquipmentId, "wearing", 0)
-- 更新玩家数据
PlayerFightProxy:UpdatePlayerFightData(Player)
end
-- 获取穿戴中的装备UniqueId
function EquipmentProxy:GetPlayerWearingEquipmentUniqueId(Player: Player)
local wearingEquipmentUniqueId = {}
-- 穿戴中的填入
for _, EquipmentData in ArchiveProxy.pData[Player.UserId][STORE_NAME] do
if EquipmentData.wearing > 0 then
wearingEquipmentUniqueId[EquipmentData.wearing] = EquipmentData.id
end
end
-- 补全空缺没填进去的槽位
local wearingNumber = PlayerInfoProxy:GetPlayerAttributesUpgrade(Player, "wearingNumber")
if wearingNumber <= 0 then return wearingEquipmentUniqueId end
for i = 1, wearingNumber do
if not wearingEquipmentUniqueId[i] then wearingEquipmentUniqueId[i] = 0 end
end
return wearingEquipmentUniqueId
end
-- 获取装备属性(汇总,不进行最终属性计算)
function EquipmentProxy:GetPlayerAttributes(Player: Player)
local AttributesData = {}
for _, EquipmentData in ArchiveProxy.pData[Player.UserId][STORE_NAME] do
if EquipmentData.wearing > 0 then
-- 增加装备基础属性
for AttributeName, AttributeValue in EquipmentData.attributes do
if AttributeName == "atkSpeed" then
if EquipmentData.wearing == 1 then
Utils:TableSafeAddValue(AttributesData, AttributeName, AttributeValue)
end
else
Utils:TableSafeAddValue(AttributesData, AttributeName, AttributeValue)
end
end
-- 增加装备额外属性
Utils:TableSafeAddTableValue(AttributesData, EquipmentData.exAttributes)
-- 增加装备元素属性
Utils:TableSafeAddTableValue(AttributesData, EquipmentData.elements)
-- 增加装备元素抗性
Utils:TableSafeAddTableValue(AttributesData, EquipmentData.elementDef)
end
end
return AttributesData
end
-- 获取装备数据
function EquipmentProxy:GetEquipmentData(Player: Player, EquipmentUniqueId: number)
local EquipmentData = ArchiveProxy.pData[Player.UserId][STORE_NAME][EquipmentUniqueId]
return EquipmentData
end
function EquipmentProxy:OnPlayerRemoving(Player: Player)
end
ReplicatedStorage.Remotes.PlayerRemoving.Event:Connect(function(PlayerUserId: string)
EquipmentProxy:OnPlayerRemoving(PlayerUserId)
end)
RE_WearEquipment.OnServerEvent:Connect(function(Player: Player, EquipmentUniqueId: number, SlotId: number, Unwear: boolean?)
if Unwear then
EquipmentProxy:UnwearEquipment(Player, EquipmentUniqueId)
else
print(Player, EquipmentUniqueId, SlotId)
EquipmentProxy:WearEquipment(Player, EquipmentUniqueId, SlotId)
end
end)
return EquipmentProxy