diff --git a/excel/attribute.xlsx b/excel/attribute.xlsx index 1a0a583..47a54e8 100644 Binary files a/excel/attribute.xlsx and b/excel/attribute.xlsx differ diff --git a/excel/cha.xlsx b/excel/cha.xlsx index 9a1d37a..5f61c45 100644 Binary files a/excel/cha.xlsx and b/excel/cha.xlsx differ diff --git a/excel/equipment.xlsx b/excel/equipment.xlsx index 0697203..38ef622 100644 Binary files a/excel/equipment.xlsx and b/excel/equipment.xlsx differ diff --git a/excel/global.xlsx b/excel/global.xlsx new file mode 100644 index 0000000..ac104d8 Binary files /dev/null and b/excel/global.xlsx differ diff --git a/excel/item.xlsx b/excel/item.xlsx index d84a7a0..dcab07d 100644 Binary files a/excel/item.xlsx and b/excel/item.xlsx differ diff --git a/excel/language.xlsx b/excel/language.xlsx new file mode 100644 index 0000000..6be7765 Binary files /dev/null and b/excel/language.xlsx differ diff --git a/excel/player.xlsx b/excel/player.xlsx deleted file mode 100644 index 987a085..0000000 Binary files a/excel/player.xlsx and /dev/null differ diff --git a/src/ReplicatedStorage/Json/Attributes.json b/src/ReplicatedStorage/Json/Attributes.json index 28e35a7..ae4d652 100644 --- a/src/ReplicatedStorage/Json/Attributes.json +++ b/src/ReplicatedStorage/Json/Attributes.json @@ -4,24 +4,26 @@ {"id":3,"type":1,"effectAttribute":"swordAtk","battleValue":[1,10]}, {"id":4,"type":2,"effectAttribute":"swordWearBase","battleValue":[1,10]}, {"id":5,"type":2,"effectAttribute":"swordWearSpe","battleValue":[1,10]}, -{"id":6,"type":1,"effectAttribute":"fireAtk","battleValue":[1,10]}, -{"id":7,"type":1,"effectAttribute":"iceAtk","battleValue":[1,10]}, -{"id":8,"type":1,"effectAttribute":"lightAtk","battleValue":[1,10]}, -{"id":9,"type":1,"effectAttribute":"shadowAtk","battleValue":[1,10]}, +{"id":6,"type":2,"effectAttribute":"fireAtk","battleValue":[1,10]}, +{"id":7,"type":2,"effectAttribute":"iceAtk","battleValue":[1,10]}, +{"id":8,"type":2,"effectAttribute":"lightAtk","battleValue":[1,10]}, +{"id":9,"type":2,"effectAttribute":"shadowAtk","battleValue":[1,10]}, {"id":10,"type":1,"effectAttribute":"fireDef","battleValue":[1,10]}, {"id":11,"type":1,"effectAttribute":"iceDef","battleValue":[1,10]}, {"id":12,"type":1,"effectAttribute":"lightDef","battleValue":[1,10]}, {"id":13,"type":1,"effectAttribute":"shadowDef","battleValue":[1,10]}, +{"id":14,"type":2,"effectAttribute":"attackRate","battleValue":[1,10]}, +{"id":15,"type":2,"effectAttribute":"hpRate","battleValue":[1,10]}, +{"id":16,"type":2,"effectAttribute":"atkSpeed","battleValue":[1,10]}, {"id":20,"type":2,"effectAttribute":"critRate","battleValue":[1,10]}, {"id":21,"type":2,"effectAttribute":"critDamageRate","battleValue":[1,10]}, {"id":22,"type":2,"effectAttribute":"atkSpeedRate","battleValue":[1,10]}, {"id":23,"type":2,"effectAttribute":"cdRate","battleValue":[1,10]}, -{"id":24,"type":2,"effectAttribute":"hpRate","battleValue":[1,10]}, -{"id":25,"type":1,"effectAttribute":"mpBonus","battleValue":[1,10]}, -{"id":26,"type":2,"effectAttribute":"mpReduceRate","battleValue":[1,10]}, -{"id":27,"type":1,"effectAttribute":"mpRecoverBonus","battleValue":[1,10]}, -{"id":28,"type":2,"effectAttribute":"vampireRate","battleValue":[1,10]}, -{"id":29,"type":2,"effectAttribute":"coinBonus","battleValue":[1,10]}, +{"id":24,"type":1,"effectAttribute":"mpBonus","battleValue":[1,10]}, +{"id":25,"type":2,"effectAttribute":"mpReduceRate","battleValue":[1,10]}, +{"id":26,"type":1,"effectAttribute":"mpRecoverBonus","battleValue":[1,10]}, +{"id":27,"type":2,"effectAttribute":"vampireRate","battleValue":[1,10]}, +{"id":28,"type":2,"effectAttribute":"coinBonus","battleValue":[1,10]}, {"id":50,"type":1,"effectAttribute":"wearNumber","battleValue":[1,10]}, {"id":51,"type":1,"effectAttribute":"skillNumber","battleValue":[1,10]}, {"id":52,"type":1,"effectAttribute":"extraAttributeNumber","battleValue":[1,10]}, diff --git a/src/ReplicatedStorage/Json/AttributesUpgrade.json b/src/ReplicatedStorage/Json/AttributesUpgrade.json index c8db73d..6510e37 100644 --- a/src/ReplicatedStorage/Json/AttributesUpgrade.json +++ b/src/ReplicatedStorage/Json/AttributesUpgrade.json @@ -5,7 +5,7 @@ {"id":4,"type":1,"effectAttribute":"swordWearBase","cost":[1,10,20],"lvAdd":[10,20],"battleValueLimit":[5,20],"maxLv":null}, {"id":5,"type":1,"effectAttribute":"swordWearSpe","cost":[1,10,20],"lvAdd":[10,20],"battleValueLimit":[5,20],"maxLv":null}, {"id":10,"type":2,"effectAttribute":"wearNumber","cost":[1,10,20],"lvAdd":[1,1],"battleValueLimit":[5,20],"maxLv":4}, -{"id":11,"type":2,"effectAttribute":"skillNumber","cost":[1,10,20],"lvAdd":[1,1],"battleValueLimit":[5,20],"maxLv":3}, +{"id":11,"type":2,"effectAttribute":"abilityNumber","cost":[1,10,20],"lvAdd":[1,1],"battleValueLimit":[5,20],"maxLv":3}, {"id":12,"type":2,"effectAttribute":"extraAttributeNumber","cost":[1,10,20],"lvAdd":[1,1],"battleValueLimit":[5,20],"maxLv":3}, {"id":13,"type":2,"effectAttribute":"elementNumber","cost":[1,10,20],"lvAdd":[1,1],"battleValueLimit":[5,20],"maxLv":3}, {"id":14,"type":2,"effectAttribute":"elementDefNumber","cost":[1,10,20],"lvAdd":[1,1],"battleValueLimit":[5,20],"maxLv":3}, diff --git a/src/ReplicatedStorage/Json/Character.json b/src/ReplicatedStorage/Json/Character.json index 9b0036b..92d553a 100644 --- a/src/ReplicatedStorage/Json/Character.json +++ b/src/ReplicatedStorage/Json/Character.json @@ -1,3 +1,3 @@ [ -{"id":1,"name":1,"attack":10,"hp":100,"walkSpeed":10,"attackSpeed":2} +{"id":1,"name":1,"attack":10,"hp":100,"walkSpeed":10,"atkSpeed":1} ] \ No newline at end of file diff --git a/src/ReplicatedStorage/Json/Equipment.json b/src/ReplicatedStorage/Json/Equipment.json index 2c10059..67ca107 100644 --- a/src/ReplicatedStorage/Json/Equipment.json +++ b/src/ReplicatedStorage/Json/Equipment.json @@ -1,3 +1,3 @@ [ -{"id":1,"type":1,"name":1,"attributes":[1,20,2,20],"recycle":10} +{"id":1,"type":1,"name":1,"attributes":[14,200,10,15,200,10,16,100,0],"recycle":10} ] \ No newline at end of file diff --git a/src/ReplicatedStorage/Json/ExAttributes.json b/src/ReplicatedStorage/Json/ExAttributes.json index 9808b37..2fe40e6 100644 --- a/src/ReplicatedStorage/Json/ExAttributes.json +++ b/src/ReplicatedStorage/Json/ExAttributes.json @@ -1,12 +1,20 @@ [ -{"id":20,"value":[10,20]}, -{"id":21,"value":[10,20]}, -{"id":22,"value":[10,20]}, -{"id":23,"value":[10,20]}, -{"id":24,"value":[10,20]}, -{"id":25,"value":[10,20]}, -{"id":26,"value":[10,20]}, -{"id":27,"value":[10,20]}, -{"id":28,"value":[10,20]}, -{"id":29,"value":[10,20]} +{"id":20,"type":1,"randomValue":[10,20],"lvBonus":[1,2]}, +{"id":21,"type":1,"randomValue":[10,20],"lvBonus":[1,2]}, +{"id":22,"type":1,"randomValue":[10,20],"lvBonus":[1,2]}, +{"id":23,"type":1,"randomValue":[10,20],"lvBonus":[1,2]}, +{"id":24,"type":1,"randomValue":[10,20],"lvBonus":[1,2]}, +{"id":25,"type":1,"randomValue":[10,20],"lvBonus":[3,2,10]}, +{"id":26,"type":1,"randomValue":[10,20],"lvBonus":[5,2,10]}, +{"id":27,"type":1,"randomValue":[10,20],"lvBonus":[5,2,10]}, +{"id":28,"type":1,"randomValue":[10,20],"lvBonus":[1,2,10]}, +{"id":29,"type":1,"randomValue":[10,20],"lvBonus":[1,2]}, +{"id":6,"type":2,"randomValue":[10,20],"lvBonus":[1,2]}, +{"id":7,"type":2,"randomValue":[10,20],"lvBonus":[1,2]}, +{"id":8,"type":2,"randomValue":[10,20],"lvBonus":[1,2]}, +{"id":9,"type":2,"randomValue":[10,20],"lvBonus":[1,2]}, +{"id":10,"type":3,"randomValue":[10,20],"lvBonus":[1,2]}, +{"id":11,"type":3,"randomValue":[10,20],"lvBonus":[1,2]}, +{"id":12,"type":3,"randomValue":[10,20],"lvBonus":[1,2]}, +{"id":13,"type":3,"randomValue":[10,20],"lvBonus":[1,2]} ] \ No newline at end of file diff --git a/src/ReplicatedStorage/Json/Forge.json b/src/ReplicatedStorage/Json/Forge.json new file mode 100644 index 0000000..1a4963c --- /dev/null +++ b/src/ReplicatedStorage/Json/Forge.json @@ -0,0 +1,17 @@ +[ +{"id":1,"cost":[2,20]}, +{"id":2,"cost":[2,30]}, +{"id":3,"cost":[2,40]}, +{"id":4,"cost":[2,50]}, +{"id":5,"cost":[2,60]}, +{"id":6,"cost":[2,70]}, +{"id":7,"cost":[2,80]}, +{"id":8,"cost":[2,90]}, +{"id":9,"cost":[2,100]}, +{"id":10,"cost":[2,110]}, +{"id":11,"cost":[2,120]}, +{"id":12,"cost":[2,130]}, +{"id":13,"cost":[2,140]}, +{"id":14,"cost":[2,150]}, +{"id":15,"cost":[2,160]} +] \ No newline at end of file diff --git a/src/ReplicatedStorage/Json/ItemProp.json b/src/ReplicatedStorage/Json/ItemProp.json index 3ad7d02..e2858bd 100644 --- a/src/ReplicatedStorage/Json/ItemProp.json +++ b/src/ReplicatedStorage/Json/ItemProp.json @@ -1,6 +1,7 @@ [ {"id":1,"type":1,"typeArgs":[],"quality":4,"iconId":1,"nameId":10001,"textId":20001,"buyPrice":[],"sellPrice":[],"use":[],"showPackage":null}, {"id":2,"type":1,"typeArgs":[],"quality":4,"iconId":2,"nameId":10002,"textId":20002,"buyPrice":[],"sellPrice":[],"use":[],"showPackage":null}, +{"id":3,"type":1,"typeArgs":[],"quality":2,"iconId":3,"nameId":10003,"textId":20003,"buyPrice":[],"sellPrice":[],"use":[],"showPackage":null}, {"id":11,"type":1,"typeArgs":[],"quality":1,"iconId":11,"nameId":10011,"textId":20011,"buyPrice":[],"sellPrice":[],"use":[],"showPackage":null}, {"id":10000,"type":4,"typeArgs":[],"quality":1,"iconId":12,"nameId":20000,"textId":30000,"buyPrice":[11,10],"sellPrice":[11,10],"use":[],"showPackage":null}, {"id":10001,"type":4,"typeArgs":[],"quality":2,"iconId":13,"nameId":20001,"textId":30001,"buyPrice":[11,20],"sellPrice":[11,20],"use":[],"showPackage":null}, diff --git a/src/ReplicatedStorage/Json/LvUpgrade.json b/src/ReplicatedStorage/Json/LvUpgrade.json new file mode 100644 index 0000000..6447b60 --- /dev/null +++ b/src/ReplicatedStorage/Json/LvUpgrade.json @@ -0,0 +1,62 @@ +[ +{"id":1,"exp":10}, +{"id":2,"exp":20}, +{"id":3,"exp":30}, +{"id":4,"exp":40}, +{"id":5,"exp":50}, +{"id":6,"exp":60}, +{"id":7,"exp":70}, +{"id":8,"exp":80}, +{"id":9,"exp":90}, +{"id":10,"exp":100}, +{"id":11,"exp":110}, +{"id":12,"exp":120}, +{"id":13,"exp":130}, +{"id":14,"exp":140}, +{"id":15,"exp":150}, +{"id":16,"exp":160}, +{"id":17,"exp":170}, +{"id":18,"exp":180}, +{"id":19,"exp":190}, +{"id":20,"exp":200}, +{"id":21,"exp":210}, +{"id":22,"exp":220}, +{"id":23,"exp":230}, +{"id":24,"exp":240}, +{"id":25,"exp":250}, +{"id":26,"exp":260}, +{"id":27,"exp":270}, +{"id":28,"exp":280}, +{"id":29,"exp":290}, +{"id":30,"exp":300}, +{"id":31,"exp":310}, +{"id":32,"exp":320}, +{"id":33,"exp":330}, +{"id":34,"exp":340}, +{"id":35,"exp":350}, +{"id":36,"exp":360}, +{"id":37,"exp":370}, +{"id":38,"exp":380}, +{"id":39,"exp":390}, +{"id":40,"exp":400}, +{"id":41,"exp":410}, +{"id":42,"exp":420}, +{"id":43,"exp":430}, +{"id":44,"exp":440}, +{"id":45,"exp":450}, +{"id":46,"exp":460}, +{"id":47,"exp":470}, +{"id":48,"exp":480}, +{"id":49,"exp":490}, +{"id":50,"exp":500}, +{"id":51,"exp":510}, +{"id":52,"exp":520}, +{"id":53,"exp":530}, +{"id":54,"exp":540}, +{"id":55,"exp":550}, +{"id":56,"exp":560}, +{"id":57,"exp":570}, +{"id":58,"exp":580}, +{"id":59,"exp":590}, +{"id":60,"exp":600} +] \ No newline at end of file diff --git a/src/ReplicatedStorage/Json/Param.json b/src/ReplicatedStorage/Json/Param.json new file mode 100644 index 0000000..5fcb8c8 --- /dev/null +++ b/src/ReplicatedStorage/Json/Param.json @@ -0,0 +1,3 @@ +[ +{"id":1,"key":"quality_bonus","intValue":null,"stringValue":null,"intArray":[100,125,150,200,275,375]} +] \ No newline at end of file diff --git a/src/ReplicatedStorage/Json/Reward.json b/src/ReplicatedStorage/Json/Reward.json new file mode 100644 index 0000000..e15bd97 --- /dev/null +++ b/src/ReplicatedStorage/Json/Reward.json @@ -0,0 +1,7 @@ +[ +{"id":1,"timeId":1,"rewards":[2,100]}, +{"id":2,"timeId":1,"rewards":[2,100]}, +{"id":3,"timeId":1,"rewards":[2,100]}, +{"id":10,"timeId":1000,"rewards":[6,15]}, +{"id":11,"timeId":1003,"rewards":[6,5]} +] \ No newline at end of file diff --git a/src/ReplicatedStorage/Tools/Utils.luau b/src/ReplicatedStorage/Tools/Utils.luau index 019c897..388561e 100644 --- a/src/ReplicatedStorage/Tools/Utils.luau +++ b/src/ReplicatedStorage/Tools/Utils.luau @@ -26,7 +26,9 @@ end function Utils:SetAttributesList(Object: Instance, Attributes: table) for Attribute, Value in Attributes do - Object:SetAttribute(Attribute, Value) + if type(Value) ~= "table" then + Object:SetAttribute(Attribute, Value) + end end end @@ -95,6 +97,26 @@ function Utils:GetRandomIdFromJsonWithType(JsonData: table, Type: number, Except return randomId end +-- 随机获取权重Index +function Utils:GetRandomWeightIndex(WeightTable: table) + local totalWeight = 0 + for _, weight in ipairs(WeightTable) do + totalWeight = totalWeight + weight + end + if totalWeight == 0 then + return nil -- 没有有效权重 + end + local rng = Random.new() + local rand = rng:NextInteger(1, totalWeight) + local sum = 0 + for i, weight in ipairs(WeightTable) do + sum = sum + weight + if rand <= sum then + return i + end + end +end + function Utils:GetMaxIdFromJson(JsonData: table) local maxId = 0 for _, item in ipairs(JsonData) do @@ -138,9 +160,17 @@ function Utils:CreateDataInstance(Player: Player, UniqueId: number, EquipmentDat end local Config = Instance.new("Configuration") Config.Name = UniqueId - -- TODO: 子表数据也要处理 Utils:SetAttributesList(Config, EquipmentData) Config.Parent = Folder + + for KeyName, Value in EquipmentData do + if type(Value) == "table" then + local newKeyConfig = Instance.new("Configuration") + newKeyConfig.Name = KeyName + Utils:SetAttributesList(newKeyConfig, Value) + newKeyConfig.Parent = Config + end + end return Config end @@ -165,6 +195,30 @@ function Utils:DeepCopyTable(t: table) end return newTable end + +-- 合并表(加法合并) +function Utils:MergeTable(t1: table, t2: table) + for k, v in pairs(t2) do + if type(v) == "number" then + t1[k] = t1[k] + v + end + end + return t1 +end + +-- 给表增加key,value(加法计算) +function Utils:TableSafeAddValue(AttributesData: table, AttributeName: string, AttributeValue: number) + AttributesData[AttributeName] = (AttributesData[AttributeName] or 0) + AttributeValue +end + +-- 给表增加key,value(加法计算),按第二个参数表的内容增加 +function Utils:TableSafeAddTableValue(AttributesData: table, AddTableValue: table) + for AttributeName, AttributeValue in AddTableValue do + AttributesData[AttributeName] = (AttributesData[AttributeName] or 0) + AttributeValue + end +end + + -------------------------------------------------------------------------------- return Utils \ No newline at end of file diff --git a/src/Server/ServerMain/init.server.luau b/src/Server/ServerMain/init.server.luau index b236511..f4ac118 100644 --- a/src/Server/ServerMain/init.server.luau +++ b/src/Server/ServerMain/init.server.luau @@ -94,6 +94,9 @@ local function OnPlayerAdded(Player: Player) Proxies.PlayerInfoProxy:InitPlayer(Player) Proxies.MobsProxy:InitPlayer(Player) Proxies.LevelProxy:InitPlayer(Player) + Proxies.AbilityProxy:InitPlayer(Player) + Proxies.GemProxy:InitPlayer(Player) + Proxies.BookProxy:InitPlayer(Player) Proxies.PlayerFightProxy:InitPlayer(Player) end diff --git a/src/ServerStorage/Modules/Behaviours/SwordWave.luau b/src/ServerStorage/Modules/Behaviours/SwordWave.luau index 2ded39c..24370f5 100644 --- a/src/ServerStorage/Modules/Behaviours/SwordWave.luau +++ b/src/ServerStorage/Modules/Behaviours/SwordWave.luau @@ -27,6 +27,7 @@ function SwordWave:Init(PlayerAI, Character: TypeList.Character, Player: Player) self.Player = Player setmetatable(self, SwordWave) self.OrgCooldown = COOLDOWN + self:StartCooldownTask() -- 客户端表现 self:SendPerformanceEvent("Init", self.Player, script.Name, true, {}) diff --git a/src/ServerStorage/Proxy/AbilityProxy.luau b/src/ServerStorage/Proxy/AbilityProxy.luau index ff4aa45..6598ec5 100644 --- a/src/ServerStorage/Proxy/AbilityProxy.luau +++ b/src/ServerStorage/Proxy/AbilityProxy.luau @@ -1,4 +1,4 @@ --- 玩家通用信息 +-- 技能系统(存储用) local AbilityProxy = {} --> Services @@ -168,7 +168,16 @@ function AbilityProxy:WearAbility(Player: Player, AbilityUniqueId: number, Equip end end - -- TODO: 获取这个装备最多穿几个技能,穿戴数量>=穿戴上限就返回 + if EquipmentData.abilitySlotNumber <= 0 then + RE_PlayerTip:FireClient(Player, "装备没有技能槽位") + return + end + + -- 检查槽位数量是否充足 + if wearingCount >= EquipmentData.abilitySlotNumber then + RE_PlayerTip:FireClient(Player, "装备已满技能槽位") + return + end -- 穿戴技能 UniqueData.wearing = EquipmentUniqueId @@ -211,6 +220,22 @@ function AbilityProxy:GetRandomAbilityId(ExceptIdList: table) return candidateIds[idx] end +-- 获取穿戴中的技能 +function AbilityProxy:GetPlayerWearingAbilityData(Player: Player) + local wearingAbilityUniqueId = {} + local behaviourNames = {} + -- 穿戴中的填入 + local EquipmentProxy = require(ServerStorage.Proxy.EquipmentProxy) + local wearingEquipments = EquipmentProxy:GetPlayerWearingEquipmentUniqueId(Player) + for _, AbilityData in ArchiveProxy.pData[Player.UserId][STORE_NAME].Ability do + if AbilityData.wearing > 0 and table.find(wearingEquipments, AbilityData.wearing) then + table.insert(wearingAbilityUniqueId, AbilityData.id) + local AbilityData = Utils:GetIdDataFromJson(JsonAbility, AbilityData.orgId) + table.insert(behaviourNames, AbilityData.behaviourName) + end + end + return wearingAbilityUniqueId, behaviourNames +end -------------------------------------------------------------------------------- -- 获取技能属性 diff --git a/src/ServerStorage/Proxy/BookProxy.luau b/src/ServerStorage/Proxy/BookProxy.luau new file mode 100644 index 0000000..0befcbc --- /dev/null +++ b/src/ServerStorage/Proxy/BookProxy.luau @@ -0,0 +1,126 @@ +-- 图鉴系统 +local BookProxy = {} + +--> Services +local ReplicatedStorage = game:GetService("ReplicatedStorage") +local ServerStorage = game:GetService("ServerStorage") + +--> Variables +local Utils = require(ReplicatedStorage.Tools.Utils) +local ArchiveProxy = require(ServerStorage.Proxy.ArchiveProxy) + +--> Json +local JsonItem = require(ReplicatedStorage.Json.ItemProp) +local JsonGem = require(ReplicatedStorage.Json.Gem) + +--> Events +local RE_PlayerTip = ReplicatedStorage.Events.RE_PlayerTip +local RE_UpgradeAttributes = ReplicatedStorage.Events.RE_UpgradeAttributes + +--> Constants +local STORE_NAME = "Book" + +-------------------------------------------------------------------------------- + +-- 获取玩家信息文件夹 +local function GetPlayerBookFolder(Player: Player) + local pData = Utils:GetPlayerDataFolder(Player) + if not pData then return end + local BookFolder = pData:FindFirstChild("Book") + return BookFolder +end + +-------------------------------------------------------------------------------- + +-- 初始化玩家 +function BookProxy:InitPlayer(Player: Player) + local pData = Utils:GetPlayerDataFolder(Player) + if not pData then return end + local BookFolder = Utils:CreateFolder("Book", pData) + + -- 新玩家数据初始化 + if not ArchiveProxy.pData[Player.UserId][STORE_NAME] then + ArchiveProxy.pData[Player.UserId][STORE_NAME] = {} + ArchiveProxy.pData[Player.UserId][STORE_NAME].Books = {} + end + + -- 创建玩家信息实例 + for BookId, BookData in ArchiveProxy.pData[Player.UserId][STORE_NAME].Books do + Utils:CreateDataInstance(Player, BookId, BookData, BookFolder) + end +end + +-------------------------------------------------------------------------------- + +-- 添加图鉴记录 +function BookProxy:AddBook(Player: Player, BookId: number, UniqueEquipmentId: number) + local pData = Utils:GetPlayerDataFolder(Player) + if not pData then return end + + local BookFolder = GetPlayerBookFolder(Player) + if not BookFolder then return end + + local EquipmentProxy = require(ServerStorage.Proxy.EquipmentProxy) + local EquipmentData = EquipmentProxy:GetEquipmentData(Player, UniqueEquipmentId) + if not EquipmentData then return end + + local orgBookData = ArchiveProxy.pData[Player.UserId][STORE_NAME].Books[BookId] + -- 检查是否已经存在 + if orgBookData then + -- 图鉴没原先品质高就返回 + if orgBookData.quality > EquipmentData.quality then return end + else + -- 原来没有时解锁图鉴 + BookProxy:UnlockBook(Player, BookId) + end + + -- 添加图鉴记录 + ArchiveProxy.pData[Player.UserId][STORE_NAME].Books[BookId] = { + timestamp = tick(), + quality = EquipmentData.quality, + } + local bookInstance = BookFolder:FindFirstChild(BookId) + bookInstance:SetAttribute("quality", ArchiveProxy.pData[Player.UserId][STORE_NAME].Books[BookId].quality) + bookInstance:SetAttribute("timestamp", ArchiveProxy.pData[Player.UserId][STORE_NAME].Books[BookId].timestamp) +end + +-- 解锁图鉴 +function BookProxy:UnlockBook(Player: Player, BookId: number) + local pData = Utils:GetPlayerDataFolder(Player) + if not pData then return end + + local BookFolder = GetPlayerBookFolder(Player) + if not BookFolder then return end + + -- 添加图鉴记录 + ArchiveProxy.pData[Player.UserId][STORE_NAME].Books[BookId] = { + timestamp = 0, + quality = 0, + } + Utils:CreateDataInstance(Player, BookId, ArchiveProxy.pData[Player.UserId][STORE_NAME].Books[BookId], BookFolder) +end + +-- 检查是否解锁对应图鉴 +function BookProxy:IsBookUnlocked(Player: Player, BookId: number) + return ArchiveProxy.pData[Player.UserId][STORE_NAME].Books[BookId] ~= nil +end + +-------------------------------------------------------------------------------- + +-- TODO: 获取玩家属性(之后要是图鉴加属性就在这) +function BookProxy:GetPlayerAttributes(Player: Player) + local attributesList = {} + return attributesList +end + +-------------------------------------------------------------------------------- + +function BookProxy:OnPlayerRemoving(Player: Player) + +end + +ReplicatedStorage.Remotes.PlayerRemoving.Event:Connect(function(Player: Player) + BookProxy:OnPlayerRemoving(Player) +end) + +return BookProxy \ No newline at end of file diff --git a/src/ServerStorage/Proxy/EquipmentProxy.luau b/src/ServerStorage/Proxy/EquipmentProxy.luau index 6164bec..f489d70 100644 --- a/src/ServerStorage/Proxy/EquipmentProxy.luau +++ b/src/ServerStorage/Proxy/EquipmentProxy.luau @@ -9,11 +9,16 @@ local ServerStorage = game:GetService("ServerStorage") 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 --> Constants local STORE_NAME = "Equipment" @@ -28,6 +33,22 @@ local function GetPlayerEquipmentFolder(Player: Player) 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 + -------------------------------------------------------------------------------- -- 初始化玩家 @@ -71,11 +92,35 @@ function EquipmentProxy:AddEquipment(Player: Player, EquipmentId: number) -- 到时候记录穿戴槽位 ResultData.wearing = 0 - -- TODO: 其他随机词条内容添加在下面 - - -- 随机生成额外属性数量 + -- 随机生成总变量 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) + ResultData.quality = quality + + -- 生成装备基础词条(固定的) + ResultData.attributes = {} + for i = 1, EquipmentData.attributesNumber, 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.name] = qualityEffectValue + end + + -- TODO: 其他随机词条内容添加在下面 + -- 随机生成额外属性数量 local maxExAttributeNumber = PlayerInfoProxy:GetPlayerInfo(Player).exAttributeNumber or 0 local exAttributeNumber = rng:NextInteger(0, maxExAttributeNumber) ResultData.maxExAttributeNumber = exAttributeNumber @@ -87,7 +132,9 @@ function EquipmentProxy:AddEquipment(Player: Player, EquipmentId: number) table.insert(spawnExAttributesId, newExAttributeId) local ExAttributeData = Utils:GetIdDataFromJson(JsonExAttributes, newExAttributeId) - local randomExAttributeValue = rng:NextInteger(ExAttributeData.randomValue[1], ExAttributeData.randomValue[2]) + 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 @@ -106,7 +153,9 @@ function EquipmentProxy:AddEquipment(Player: Player, EquipmentId: number) table.insert(spawnElementsId, newElementAttributeId) local ElementAttributeData = Utils:GetIdDataFromJson(JsonExAttributes, newElementAttributeId) - local randomElementAttributeValue = rng:NextInteger(ElementAttributeData.randomValue[1], ElementAttributeData.randomValue[2]) + 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 @@ -125,7 +174,9 @@ function EquipmentProxy:AddEquipment(Player: Player, EquipmentId: number) table.insert(spawnElementDefId, newElementDefId) local ElementDefAttributeData = Utils:GetIdDataFromJson(JsonExAttributes, newElementDefId) - local randomElementDefAttributeValue = rng:NextInteger(ElementDefAttributeData.randomValue[1], ElementDefAttributeData.randomValue[2]) + 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 @@ -167,6 +218,10 @@ function EquipmentProxy:AddEquipment(Player: Player, EquipmentId: number) ArchiveProxy.pData[Player.UserId][UniqueId] = ResultData Utils:CreateDataInstance(Player, UniqueId, ResultData, GetPlayerEquipmentFolder(Player)) + + -- 添加图鉴记录 + local BookProxy = require(ServerStorage.Proxy.BookProxy) + BookProxy:AddBook(Player, EquipmentId, UniqueId) end -- 回收装备 @@ -177,9 +232,14 @@ function EquipmentProxy:RecycleEquipment(Player: Player, EquipmentId: number) local EquipmentData = ArchiveProxy.pData[Player.UserId][STORE_NAME][EquipmentId] if not EquipmentData then return end - -- TODO:根据对应功能模块生成对应技能 + -- 根据对应功能模块进行对应回收 + 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 @@ -190,12 +250,95 @@ function EquipmentProxy:RecycleEquipment(Player: Player, EquipmentId: number) end -- 穿戴装备 -function EquipmentProxy:WearEquipment(Player: Player, EquipmentId: number) +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.wearingNumber 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 -- 获取装备数据 diff --git a/src/ServerStorage/Proxy/GemProxy.luau b/src/ServerStorage/Proxy/GemProxy.luau index f3753a5..58afa71 100644 --- a/src/ServerStorage/Proxy/GemProxy.luau +++ b/src/ServerStorage/Proxy/GemProxy.luau @@ -1,4 +1,4 @@ --- 玩家通用信息 +-- 宝石系统 local GemProxy = {} --> Services @@ -157,7 +157,25 @@ function GemProxy:WearGem(Player: Player, GemUniqueId: number, EquipmentUniqueId return end - -- TODO: 检查对应装备是否有充足的宝石槽位 + -- 检查对应装备是否有充足的宝石槽位 + local EquipmentData = EquipmentProxy:GetEquipmentData(Player, EquipmentUniqueId) + if not EquipmentData then warn('无法获取装备数据: ' , Player.Name, EquipmentUniqueId) return end + if EquipmentData.gemSlotNumber <= 0 then + RE_PlayerTip:FireClient(Player, "装备没有宝石槽位") + return + end + + -- 检查槽位数量是否充足 + local wearingGemNumber = 0 + for _, gemData in ArchiveProxy.pData[Player.UserId][STORE_NAME].Gems do + if gemData.wearing == EquipmentUniqueId then + wearingGemNumber += 1 + end + end + if wearingGemNumber >= EquipmentData.gemSlotNumber then + RE_PlayerTip:FireClient(Player, "装备已满宝石槽位") + return + end -- 穿戴 GemData.wearing = EquipmentUniqueId @@ -202,14 +220,14 @@ end function GemProxy:GetPlayerGemWearingAttributes(Player: Player) if not Player then warn('获取玩家属性失败: ', Player.Name) return end local playerGems = ArchiveProxy.pData[Player.UserId][STORE_NAME].Gems + + local EquipmentProxy = require(ServerStorage.Proxy.EquipmentProxy) + local wearingEquipments = EquipmentProxy:GetPlayerWearingEquipmentUniqueId(Player) + local attributes = {} for _, gemData in playerGems do - if gemData.wearing ~= 0 then - if attributes[gemData.effectAttribute] then - attributes[gemData.effectAttribute] = attributes[gemData.effectAttribute] + gemData.attributeValue - else - attributes[gemData.effectAttribute] = gemData.attributeValue - end + if gemData.wearing ~= 0 and table.find(wearingEquipments, gemData.wearing) then + Utils:TableSafeAddValue(attributes, gemData.effectAttribute, gemData.attributeValue) end end return attributes diff --git a/src/ServerStorage/Proxy/LevelProxy.luau b/src/ServerStorage/Proxy/LevelProxy.luau index 51aca8f..a15783d 100644 --- a/src/ServerStorage/Proxy/LevelProxy.luau +++ b/src/ServerStorage/Proxy/LevelProxy.luau @@ -88,6 +88,8 @@ end local EXCEPT_KEY = { "Task", "Mobs"} local function ChangeValue(Player: Player, Folder: Instance, LevelKey: string, LevelValue: any) if not Player or not Folder or not LevelKey then warn("LevelProxy ChangeValue", Player.UserId, Folder.Name, LevelKey, LevelValue) return end + if table.find(EXCEPT_KEY, LevelKey) then return end + local ValueInstance = Folder:FindFirstChild(LevelKey) if not ValueInstance then warn("ValueInstance not found", LevelKey) return end @@ -99,7 +101,7 @@ local function ChangeValue(Player: Player, Folder: Instance, LevelKey: string, L end storeTable[LevelKey] = LevelValue - if not table.find(EXCEPT_KEY, LevelKey) then ValueInstance.Value = LevelValue end + ValueInstance.Value = LevelValue end -- 怪物死亡,由初始化时传入 @@ -249,7 +251,6 @@ function LevelProxy:ChallengeEnd(Player: Player, result: boolean) end -- 清除剩余怪物 - print("清除剩余怪物", LevelProxy.pData[Player.UserId].Mobs) for _, mob in LevelProxy.pData[Player.UserId].Mobs do mob:Died(true) end LevelProxy.pData[Player.UserId].Mobs = {} diff --git a/src/ServerStorage/Proxy/PlayerFightProxy/LevelLoop.luau b/src/ServerStorage/Proxy/PlayerFightProxy/LevelLoop.luau index e3d170c..a9987e2 100644 --- a/src/ServerStorage/Proxy/PlayerFightProxy/LevelLoop.luau +++ b/src/ServerStorage/Proxy/PlayerFightProxy/LevelLoop.luau @@ -41,8 +41,6 @@ function LevelLoop:AutoChallenge() print("AutoChallenge") -- TODO: 回退有bug,不能一关一关回退 - -- 重置玩家状态(先临时调用角色复活,之后复杂的内容再说) - self.PlayerRole:Respawn() local LevelFolder = game.Workspace:WaitForChild("Level"):WaitForChild(self.Player.UserId) local ProgressFolder = LevelFolder:FindFirstChild("Progress") @@ -60,6 +58,8 @@ end function LevelLoop:OnChallengeEnd(Player: Player, LevelId: number, result: boolean) self.TaskAutoChallenge = task.spawn(function() task.wait(3) + -- 重置玩家状态(先临时调用角色复活,之后复杂的内容再说) + self.PlayerRole:Respawn() self:AutoChallenge() end) end diff --git a/src/ServerStorage/Proxy/PlayerFightProxy/PlayerAI.luau b/src/ServerStorage/Proxy/PlayerFightProxy/PlayerAI.luau index 54929dc..2ea3df9 100644 --- a/src/ServerStorage/Proxy/PlayerFightProxy/PlayerAI.luau +++ b/src/ServerStorage/Proxy/PlayerFightProxy/PlayerAI.luau @@ -105,6 +105,12 @@ function PlayerAI:RemoveBehaviour(BehaviourName: string) end end +-- 清除所有行为 +function PlayerAI:ClearAllBehaviour() + for _, behaviour in self.BehaviourList do behaviour:Destroy() end + self.BehaviourList = {} +end + -- 销毁AI function PlayerAI:Destroy() for _, behaviour in self.BehaviourList do behaviour:Destroy() end diff --git a/src/ServerStorage/Proxy/PlayerFightProxy/init.luau b/src/ServerStorage/Proxy/PlayerFightProxy/init.luau index 9804d7d..9676e5c 100644 --- a/src/ServerStorage/Proxy/PlayerFightProxy/init.luau +++ b/src/ServerStorage/Proxy/PlayerFightProxy/init.luau @@ -13,6 +13,7 @@ local LevelProxy = require(ServerStorage.Proxy.LevelProxy) --> Json local JsonCharacter = require(ReplicatedStorage.Json.Character) +local JsonAttributes = require(ReplicatedStorage.Json.Attributes) --> Dependencies local LevelLoop = require(script.LevelLoop) @@ -40,14 +41,24 @@ setmetatable(PlayerRole, {__index = Character}) function PlayerRole.new(Player: Player, CharacterId: number) local playerCharacter = WaitForCharacter(Player) - -- 获取玩家初始数据 + -- 获取玩家初始数据(临时初始化使用,不是真属性配置部分) local CharacterData = Utils:GetIdDataFromJson(JsonCharacter, CharacterId) if not CharacterData then warn("CharacterId Data not found", CharacterId) return end + -- 补充默认没设置的属性,暂时不添加特殊属性,因为特殊属性是系统调用的,添加也没啥用 + for _, AttributeData in JsonCharacter do + if AttributeData.id < 50 then + if not CharacterData[AttributeData.name] then CharacterData[AttributeData.name] = 0 end + end + end + + -- 调用父类Character的new方法,初始化通用属性 local self = Character.new(Player, playerCharacter, CharacterData) setmetatable(self, PlayerRole) + self.CharacterId = CharacterId + -- 玩家放到Character目录下 playerCharacter.Parent = game.Workspace.Characters return self @@ -63,8 +74,9 @@ function PlayerRole:Respawn() self:ChangeState("Died", false) self.Humanoid.WalkSpeed = self.Config.walkSpeed self:ChangeAttributeValue("hp", self.Config.maxhp) - -- 重置玩家位置 + -- TODO: 重置玩家位置 + PlayerFightProxy:UpdatePlayerFightData(self.Player) end -------------------------------------------------------------------------------- @@ -86,8 +98,9 @@ function PlayerFightProxy:InitPlayer(Player: Player) -- 生成玩家AI local PlayerAI = PlayerAI.new(Player, PlayerRole) PlayerFightProxy.pData[Player.UserId].PlayerAI = PlayerAI - PlayerAI:AddBehaviour("Move") - PlayerAI:AddBehaviour("SwordWave") + + -- 更新玩家战斗数据 + self:UpdatePlayerFightData(Player) end function PlayerFightProxy:GetPlayerRole(Player: Player) @@ -95,9 +108,74 @@ function PlayerFightProxy:GetPlayerRole(Player: Player) end function PlayerFightProxy:GetPlayerAI(Player: Player) + print(PlayerFightProxy.pData[Player.UserId]) return PlayerFightProxy.pData[Player.UserId].PlayerAI end +-- 更新玩家战斗数据(所有变动全部从这调用) +function PlayerFightProxy:UpdatePlayerFightData(Player: Player) + local PlayerInfoProxy = require(ServerStorage.Proxy.PlayerInfoProxy) + local EquipmentProxy = require(ServerStorage.Proxy.EquipmentProxy) + local AbilityProxy = require(ServerStorage.Proxy.AbilityProxy) + local GemProxy = require(ServerStorage.Proxy.GemProxy) + + + local AttributesData = {} + + -- 计算角色基础属性值 + 装备属性值 + 宝石属性值,赋值属性 + local PlayerInfoAttributes = PlayerInfoProxy:GetPlayerAttributes(Player) + AttributesData = Utils:MergeTable(AttributesData, PlayerInfoAttributes) + + local EquipmentAttributes = EquipmentProxy:GetPlayerAttributes(Player) + AttributesData = Utils:MergeTable(AttributesData, EquipmentAttributes) + + local GemAttributes = GemProxy:GetPlayerAttributes(Player) + AttributesData = Utils:MergeTable(AttributesData, GemAttributes) + + -- 角色基础数据 + local PlayerRole = self:GetPlayerRole(Player) + local CharacterData = Utils:GetIdDataFromJson(JsonCharacter, PlayerRole.CharacterId) + if not CharacterData then warn("CharacterId Data not found", PlayerRole.CharacterId) return end + -- 如果玩家装备的武器里面有了攻击速度属性,就不用默认的攻击属性进行配置 + local ExceptAttributes = {"id", "name"} + if AttributesData.atkSpeed then table.insert(ExceptAttributes, "atkSpeed") end + + for AttributeName, AttributeValue in CharacterData do + if not table.find(ExceptAttributes, AttributeName) then + Utils:TableSafeAddValue(AttributesData, AttributeName, AttributeValue) + end + end + + -- 根据汇总更新玩家属性——————实际生效计算部分 + local PlayerRole = self:GetPlayerRole(Player) + + -- 针对百分比特殊属性直接进行计算修改 + if AttributesData["hpRate"] then + AttributesData["hp"] = math.floor(AttributesData["hp"] * AttributesData["hpRate"] / 100) + end + if AttributesData["atkRate"] then + AttributesData["atk"] = math.floor(AttributesData["atk"] * AttributesData["atkRate"] / 100) + end + + -- 更新玩家属性 + for AttributeName, AttributeValue in AttributesData do + -- TODO:这里可能涉及到战斗时更换装备的属性处理,还需要再函数内部再根据剩余百分比数值变化 + PlayerRole:ChangeAttributeValue(AttributeName, AttributeValue) + end + + -- 根据技能添加玩家AI行为 + local abilityIdList, behaviourNameList = AbilityProxy:GetPlayerWearingAbilityData(Player) + local playerAI = PlayerFightProxy:GetPlayerAI(Player) + + -- TODO:设置AI行为(临时清除所有行为,添加新的玩家行为) + playerAI:ClearAllBehaviour() + for _, behaviourName in behaviourNameList do + playerAI:AddBehaviour(behaviourName) + end + playerAI:AddBehaviour("Move") + playerAI:AddBehaviour("SwordWave") +end + -- 重置玩家状态,但是不删除 function PlayerFightProxy:CleanPlayer(Player: Player) -- 玩家角色重生 diff --git a/src/ServerStorage/Proxy/PlayerInfoProxy.luau b/src/ServerStorage/Proxy/PlayerInfoProxy.luau index 0bd9790..16e31eb 100644 --- a/src/ServerStorage/Proxy/PlayerInfoProxy.luau +++ b/src/ServerStorage/Proxy/PlayerInfoProxy.luau @@ -8,14 +8,17 @@ local ServerStorage = game:GetService("ServerStorage") --> Variables local Utils = require(ReplicatedStorage.Tools.Utils) local ArchiveProxy = require(ServerStorage.Proxy.ArchiveProxy) +local BookProxy = require(ServerStorage.Proxy.BookProxy) --> Json -local JsonPlayerLv = require(ReplicatedStorage.Json.PlayerLv) +local JsonLvUpgrade = require(ReplicatedStorage.Json.LvUpgrade) local JsonItem = require(ReplicatedStorage.Json.ItemProp) local JsonAttributesUpgrade = require(ReplicatedStorage.Json.AttributesUpgrade) +local JsonForge = require(ReplicatedStorage.Json.Forge) --> Events local RE_PlayerTip = ReplicatedStorage.Events.RE_PlayerTip +local RE_Forge = ReplicatedStorage.Events.RE_Forge local RE_UpgradeAttributes = ReplicatedStorage.Events.RE_UpgradeAttributes --> Constants @@ -66,7 +69,7 @@ local STATS_DATA = { exp = {type = ENUM_STATE_TYPE.Number, value = 0}, } --- 初始化玩家状态信息 +-- 初始化玩家状态信息(采用额外添加的模式,如果没有写值,就覆盖写入) local function ExtraAddPlayerStats(Player: Player, StatsData: table) if not Player or not StatsData then return end -- 如果列表中不包含信息就添加到表中 @@ -94,6 +97,7 @@ function PlayerInfoProxy:InitPlayer(Player: Player) ArchiveProxy.pData[Player.UserId][STORE_NAME].Stats = {} ArchiveProxy.pData[Player.UserId][STORE_NAME].Items = {} ArchiveProxy.pData[Player.UserId][STORE_NAME].AttributesUpgrade = {} + ArchiveProxy.pData[Player.UserId][STORE_NAME].Forge = 1 end -- 放在外面是为了以后系统新增内容方便(同时不用在初始化数据是做写入了) @@ -109,6 +113,7 @@ function PlayerInfoProxy:InitPlayer(Player: Player) for AttributeId, AttributeLv in ArchiveProxy.pData[Player.UserId][STORE_NAME].AttributesUpgrade do CreateInfoInstance(Player, AttributesUpgradeFolder, AttributeId, "NumberValue", AttributeLv) end + CreateInfoInstance(Player, PlayerInfoFolder, "Forge", ENUM_STATE_TYPE.Number, ArchiveProxy.pData[Player.UserId][STORE_NAME].Forge) end -- 获取玩家信息 @@ -118,6 +123,19 @@ function PlayerInfoProxy:GetPlayerInfo(Player: Player) return playerInfoData end +-- 获取玩家等级 +function PlayerInfoProxy:GetPlayerLevel(Player: Player) + if not Player then warn('获取玩家等级失败: ', Player.Name) return end + local playerInfoData = ArchiveProxy.pData[Player.UserId][STORE_NAME] + return playerInfoData.Stats.level +end + +function PlayerInfoProxy:GetPlayerAttributesUpgrade(Player: Player, AttributeName: string) + if not Player or not AttributeName then warn('获取玩家属性升级失败: ', Player.Name, AttributeName) return end + local playerInfoData = ArchiveProxy.pData[Player.UserId][STORE_NAME] + return playerInfoData.AttributesUpgrade[AttributeName] or 0 +end + -- 玩家属性升级 function PlayerInfoProxy:UpgradeAttribute(Player: Player, AttributeId: number) if not Player or not AttributeId then warn('升级属性失败: ', Player.Name, AttributeId) return end @@ -142,7 +160,6 @@ function PlayerInfoProxy:UpgradeAttribute(Player: Player, AttributeId: number) -- TODO 判断战力是否足够(暂无战力计算) -- 判断是否到达等级上限 - print(nowLv, attributeData["maxLv"]) if attributeData["maxLv"] ~= nil then if nowLv >= attributeData["maxLv"] then local tip = '升级属性失败: ' .. AttributeId .. ' 已到达等级上限' @@ -180,9 +197,9 @@ function PlayerInfoProxy:AddExp(Player: Player, Exp: number) -- 数据变化 local currentLevel = playerInfoData.Stats.level - local maxLevel = Utils:GetMaxIdFromJson(JsonPlayerLv) + local maxLevel = Utils:GetMaxIdFromJson(JsonLvUpgrade) if currentLevel < maxLevel then - local requireExp = Utils:GetIdDataFromJson(JsonPlayerLv, currentLevel) + local requireExp = Utils:GetIdDataFromJson(JsonLvUpgrade, currentLevel) if playerInfoData.Stats.exp >= requireExp then playerInfoData.Stats.level = currentLevel + 1 playerInfoData.Stats.exp = playerInfoData.Stats.exp - requireExp @@ -229,12 +246,58 @@ end -- 获取物品数量 function PlayerInfoProxy:GetItemCount(Player: Player, ItemId: number) - if not Player or not ItemId then warn('获取物品数量失败: ' .. Player.Name .. ' ' .. ItemId) return end + if not Player or not ItemId then warn('获取物品数量失败: ' , Player.Name, ItemId) return end local playerInfoData = ArchiveProxy.pData[Player.UserId][STORE_NAME].Items if not playerInfoData[ItemId] then return 0 end return playerInfoData[ItemId] end +-- 打造装备 +function PlayerInfoProxy:MakeForge(Player: Player, EquipmentId: number, Count: number) + if not Player or not EquipmentId then warn('打造装备失败: ', Player.Name,EquipmentId) return end + + local PlayerInfoFolder = GetPlayerInfoFolder(Player) + if not PlayerInfoFolder then return end + + -- 检查装备图鉴是否解锁 + local BookProxy = require(ServerStorage.Proxy.BookProxy) + if not BookProxy:IsBookUnlocked(Player, EquipmentId) then + RE_PlayerTip:FireClient(Player, "装备图鉴未解锁") + return + end + + -- 锻造数量>1,判断是否到达最高锻造等级 + local ForgeLv = PlayerInfoProxy:GetPlayerInfo(Player).Forge + if Count > 1 then + local MaxForgeLv = Utils:GetMaxIdFromJson(JsonForge, ForgeLv) + if ForgeLv < MaxForgeLv then + RE_PlayerTip:FireClient(Player, "锻造等级已到达最高等级") + return + end + end + + -- 判断金钱是否足够 + local ShouldCostMoney = Utils:GetIdDataFromJson(JsonForge, ForgeLv)["cost"][2] * Count + if not self:HasEnoughItem(Player, 1, ShouldCostMoney) then + RE_PlayerTip:FireClient(Player, "金钱不足") + return + end + -- 扣钱 + self:ChangeItemCount(Player, 1, -ShouldCostMoney) + + -- 生成对应装备 + local EquipmentProxy = require(ServerStorage.Proxy.EquipmentProxy) + for i = 1, Count do + EquipmentProxy:AddEquipment(Player, EquipmentId) + end + + -- 锻造升级 + ForgeLv = ForgeLv + Count + ChangeInfoInstance(Player, PlayerInfoFolder, "Forge", ForgeLv) + + -- TODO: 添加对应奖励弹窗 +end + -------------------------------------------------------------------------------- -- 获取升级加点属性 @@ -262,6 +325,10 @@ function PlayerInfoProxy:OnPlayerRemoving(Player: Player) end +RE_Forge.OnServerEvent:Connect(function(Player: Player, EquipmentId: number, Count: number) + PlayerInfoProxy:MakeForge(Player, EquipmentId, Count) +end) + ReplicatedStorage.Remotes.PlayerRemoving.Event:Connect(function(Player: Player) PlayerInfoProxy:OnPlayerRemoving(Player) end)