2093 lines
71 KiB
Lua
2093 lines
71 KiB
Lua
---@class BP_PlayerState_C:BP_UGCPlayerState_C
|
||
--Edit Below--
|
||
UGCGameSystem.UGCRequire('Script.Common.ue_enum_custom')
|
||
UGCGameSystem.UGCRequire('Script.Common.ue_struct_custom')
|
||
UGCGameSystem.UGCRequire('Script.Global.Global')
|
||
|
||
local BP_PlayerState = {
|
||
-- [AttributeType] = { AttributeName: Value , ...}, ...
|
||
Attributes = {}, -- 玩家属性表,存放所有属性
|
||
CombatPoint = 0, -- 战力
|
||
CoinPoint = {
|
||
Total = 0,
|
||
Current = 0,
|
||
}, -- 金币
|
||
KillPoint = {
|
||
Total = 0,
|
||
Current = 0,
|
||
}, -- 杀敌点
|
||
|
||
KillCount = {
|
||
Total = 0,
|
||
Boss = 0,
|
||
}, -- 杀敌数,用于计算增加量和表示玩家击杀怪物
|
||
Level = 1, -- 等级
|
||
CurExp = 0, -- 获取的总经验
|
||
NextAddExp = 0, -- 由于被打断,之后需要添加的值
|
||
|
||
BreachInfo = {
|
||
NeedBreach = false, --是否需要突破
|
||
InBreachProgress = false, --是否正在突破中
|
||
},
|
||
|
||
BreachSuccessTime = 0, --突破成功次数
|
||
|
||
--local ItemData = {
|
||
-- WeaponId = InWeaponId,
|
||
-- Type = WeaponType,
|
||
-- NativeProps = {
|
||
-- Common = 0,
|
||
-- Plus = { },
|
||
-- },
|
||
-- Properties = { },
|
||
-- Fittings = { },
|
||
-- FittingLevel = 0,
|
||
-- }
|
||
OwnerWeapons = {},
|
||
TotalWeaponCount = 0, --当前拥有的Weapon数量
|
||
|
||
TechBuyNum = {}, -- 玩家科技表
|
||
|
||
BackupEnergyData = {}, --玩家能量信息备份
|
||
-- 需要同步的射击距离
|
||
AttackRange = 0, -- 同步的射击距离
|
||
ChallengeMonsterTime = {},
|
||
|
||
LastSpecialItems = {}, -- 保存着上一次的词条属性
|
||
|
||
--- 存放特殊词条物品,如果存在,那么就是有该属性;不存在,就取消
|
||
--- [id] = {
|
||
--- Times = 0,
|
||
--- LastTime = ServerTime,
|
||
--- }
|
||
SpecialItemTimerHandles = {
|
||
['击败'] = { },
|
||
['每秒'] = { },
|
||
['射击'] = { },
|
||
['射击%'] = { },
|
||
['周期'] = { },
|
||
['固定'] = { },
|
||
}, --保存着对应Id的Timer
|
||
|
||
--- 存放着继承的等级
|
||
InheritItems = {
|
||
['盔'] = 110,
|
||
['甲'] = 210,
|
||
},
|
||
|
||
-- 特殊物品数据存放地方,没有特定结构,数据结构 { [ID] = {}, }
|
||
SpecialThings = {},
|
||
|
||
--- 每局游戏通关之类保存的数据
|
||
--- {
|
||
--- GameTimes = 0, --游玩局数
|
||
--- GameClearanceTimes = 0, --游戏通关数
|
||
--- TotalCoinPoint = 0, --获取总金币数
|
||
--- TotalKillPoint = 0, --获取总杀敌点数
|
||
--- TotalBossKilledTimes = 0,--击杀 Boss 次数
|
||
--- TotalSuperSkill = 0, --获取总超级技能数
|
||
--- TotalSuperFitting = 0, --获取超级配件数
|
||
--- TotalUnpackTimes = 0, --总开箱次数
|
||
--- Score = 0, --积分
|
||
---
|
||
--- PlayedGames = { --通关过的游戏
|
||
--- Difficulty = Times
|
||
--- },
|
||
--- BossDropItems = {
|
||
--- ["春"] = {
|
||
--- Type: Count
|
||
--- },
|
||
--- },
|
||
--- GameDropItems = {
|
||
--- Difficulty = { Type: Count },
|
||
--- },
|
||
--- EasterEggs = { --彩蛋类
|
||
--- },
|
||
--- }
|
||
ArchiveData = nil,
|
||
|
||
-- 存一份缓存
|
||
SavedArchiveData = nil;
|
||
GameEndSavedArchiveData = {};
|
||
|
||
-- 新的一局游戏初始数据,该数据是 { Type = Value, ... }
|
||
NewGameInitialData = {},
|
||
|
||
EasterEggsData = {
|
||
},
|
||
|
||
-- 一些其他属性
|
||
AppendAttribute = {},
|
||
|
||
--当前强制引导信息
|
||
ForceGuideInfo = {
|
||
CurStepIndex = -2,
|
||
ValidStepIndex = -2,
|
||
bIsInStepProgress = false,
|
||
StepPendingList = {},
|
||
},
|
||
};
|
||
|
||
function BP_PlayerState:GetReplicatedProperties()
|
||
return
|
||
"Attributes",
|
||
"CoinPoint",
|
||
"KillPoint",
|
||
"OwnerWeapons",
|
||
"TechBuyNum",
|
||
"AttackRange",
|
||
"TotalWeaponCount",
|
||
"ChallengeMonsterTime",
|
||
"InheritItems",
|
||
"ArchiveData",
|
||
{"BreachInfo", "Lazy"},
|
||
{"ForceGuideInfo", "Lazy"},
|
||
{"SavedArchiveData", "Lazy"}
|
||
end
|
||
|
||
function BP_PlayerState:ReceiveBeginPlay()
|
||
BP_PlayerState.SuperClass.ReceiveBeginPlay(self)
|
||
|
||
if self:HasAuthority() == true then
|
||
self:BindServerEvent()
|
||
self:InitWeaponAttribute()
|
||
self:InitChallengeMonsterTime(-10000.0)
|
||
|
||
for key, _ in pairs(Tables.Tech) do
|
||
self.TechBuyNum[key] = 0
|
||
end
|
||
|
||
EventSystem.SetTimer(self, function()
|
||
--self:TestAddStone()
|
||
end, 20)
|
||
else
|
||
local CommandManager = require('Script.Manager.CommandQueneManager')
|
||
CommandManager.bPlayerStateReady = true
|
||
CommandManager:AddInitCommand(self, self.Client_Init)
|
||
UE.Log("[BP_PlayerState] *** BP_PlayerPawn Tick Init Ready PlayerKey:%s", self.PlayerKey)
|
||
end
|
||
end
|
||
|
||
function BP_PlayerState:ReceiveEndPlay()
|
||
if self:HasAuthority() then
|
||
self:UnbindServerEvent()
|
||
else
|
||
CommandQueneManager:RemoveInitCommand(self)
|
||
end
|
||
|
||
BP_PlayerState.SuperClass:ReceiveEndPlay()
|
||
end
|
||
|
||
function BP_PlayerState:Client_Init()
|
||
if self:GetOwner() == STExtraGameplayStatics.GetFirstPlayerController(self) then
|
||
GameDataManager:SetLocalPlayerState(self)
|
||
end
|
||
self:OnRep_Attributes()
|
||
self:OnRep_CoinPoint()
|
||
self:OnRep_KillPoint()
|
||
self:OnRep_OwnerWeapons()
|
||
self:OnRep_TotalWeaponCount()
|
||
self:OnRep_AttackRange()
|
||
end
|
||
|
||
function BP_PlayerState:BindServerEvent()
|
||
end
|
||
|
||
function BP_PlayerState:UnbindServerEvent()
|
||
end
|
||
|
||
function BP_PlayerState:InitArchiveData()
|
||
local ItemData = {
|
||
GameTimes = 0, --游玩局数
|
||
GameClearanceTimes = 0, --游戏通关数
|
||
TotalCoinPoint = 0, --获取总金币数
|
||
TotalKillPoint = 0, --获取总杀敌点数
|
||
TotalBossKilledTimes = 0, --击杀 Boss 次数
|
||
TotalSuperSkill = 0, --获取总超级技能数
|
||
TotalSuperFitting = 0, --获取超级配件数
|
||
TotalUnpackTimes = 0, --总开箱次数
|
||
Score = 0, --总开箱次数
|
||
|
||
PlayedGames = { --游玩过的游戏
|
||
},
|
||
BossDropItems = {
|
||
},
|
||
GameDropItems = {
|
||
},
|
||
EasterEggs = { --彩蛋类
|
||
},
|
||
}
|
||
|
||
-- 初始化
|
||
for i = 1, 13 do
|
||
--if i ~= 9 then
|
||
ItemData.EasterEggs[i] = {
|
||
Active = false, -- 是否激活
|
||
}
|
||
--end
|
||
end
|
||
|
||
return ItemData
|
||
end
|
||
|
||
-- 加载重生数据
|
||
function BP_PlayerState:LoadNewGameInitialData()
|
||
print(string.format('[BP_PlayerState:LoadNewGameInitialData] 加载到 NewGameInitialData 中'))
|
||
local Data = self.ArchiveData
|
||
local OutTable = {}
|
||
|
||
if Data == nil then
|
||
-- 说明还未加载,请检查原因
|
||
print(string.format('[BP_PlayerState:LoadNewGameInitialData] Error 按理说此处应该加载了,但是并没有显示出来'))
|
||
self.NewGameInitialData = {}
|
||
return
|
||
end
|
||
|
||
-- 通关检查
|
||
if self.ArchiveData.GameClearanceTimes > 0 then
|
||
-- i:难度(int); v:次数(int)
|
||
for i, v in pairs(self.ArchiveData.PlayedGames) do
|
||
-- 从表中进行加载,k: 可以获得奖励的次数; u: 具体奖励
|
||
for k,u in pairs(ArchiveTable.GameClearanceRewards[i]) do
|
||
if k <= v then
|
||
ArchiveTable.Funcs[ArchiveTable.ArchiveType.GameClearance](i, k, OutTable)
|
||
end
|
||
end
|
||
end
|
||
else
|
||
-- 表示第一次游玩
|
||
print(string.format('[BP_PlayerState:LoadNewGameInitialData] 第一次游玩'))
|
||
end
|
||
|
||
local Func = function(InTable, InOutTable)
|
||
for i, v in pairs(InTable) do
|
||
InOutTable[i] = v
|
||
end
|
||
end
|
||
|
||
-- 积分
|
||
ArchiveTable.Funcs[ArchiveTable.ArchiveType.Credit](self.ArchiveData.Score, OutTable)
|
||
--Func(OutTable, self.NewGameInitialData)
|
||
-- 依次判断以下内容
|
||
--- 通关
|
||
ArchiveTable.Funcs[ArchiveTable.ArchiveType.Achievement].Func("通关", self.ArchiveData.GameClearanceTimes, OutTable)
|
||
--- 击杀首领
|
||
ArchiveTable.Funcs[ArchiveTable.ArchiveType.Achievement].Func("击败", self.ArchiveData.TotalBossKilledTimes, OutTable)
|
||
--- 获得金币,单位是w
|
||
ArchiveTable.Funcs[ArchiveTable.ArchiveType.Achievement].Func("金币", self.ArchiveData.TotalCoinPoint / 10000, OutTable)
|
||
--- 获得杀敌点
|
||
ArchiveTable.Funcs[ArchiveTable.ArchiveType.Achievement].Func("科技点", self.ArchiveData.TotalKillPoint, OutTable)
|
||
--- 获得超级技能
|
||
ArchiveTable.Funcs[ArchiveTable.ArchiveType.Achievement].Func("技能", self.ArchiveData.TotalSuperSkill, OutTable)
|
||
--- 获得超级配件
|
||
ArchiveTable.Funcs[ArchiveTable.ArchiveType.Achievement].Func("配件", self.ArchiveData.TotalSuperFitting, OutTable)
|
||
--- 开箱次数
|
||
ArchiveTable.Funcs[ArchiveTable.ArchiveType.Achievement].Func("开箱", self.ArchiveData.TotalUnpackTimes, OutTable)
|
||
Func(OutTable, self.NewGameInitialData)
|
||
|
||
-- Boss 掉落物
|
||
ArchiveTable.Funcs[ArchiveTable.ArchiveType.DropBossItems](self.ArchiveData.BossDropItems, OutTable)
|
||
Func(OutTable, self.NewGameInitialData)
|
||
|
||
-- 游戏掉落物
|
||
ArchiveTable.Funcs[ArchiveTable.ArchiveType.DropGameItems](self.ArchiveData.GameDropItems, OutTable)
|
||
Func(OutTable, self.NewGameInitialData)
|
||
|
||
log_tree("[BP_PlayerState:LoadNewGameInitialData] Begin self.NewGameInitialData = ", self.NewGameInitialData);
|
||
|
||
-- 彩蛋类
|
||
|
||
for EasterIndex, Table in pairs(ArchiveTable.EasterEggs) do
|
||
if self.ArchiveData.EasterEggs[EasterIndex] == nil then
|
||
self.ArchiveData.EasterEggs[EasterIndex] = {
|
||
Active = false;
|
||
}
|
||
else
|
||
if self.ArchiveData.EasterEggs[EasterIndex].Active then
|
||
local Type = Table.Reward.Type;
|
||
if Type ~= nil then
|
||
if self.NewGameInitialData[Type] == nil then
|
||
self.NewGameInitialData[Type] = Table.Reward.Value
|
||
else
|
||
self.NewGameInitialData[Type] = self.NewGameInitialData[Type] + Table.Reward.Value
|
||
end
|
||
--print(string.format("[BP_PlayerState:LoadNewGameInitialData] Type = " .. tostring(Type)))
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
--for EasterIndex, Table in pairs(self.ArchiveData.EasterEggs) do
|
||
-- if Table and Table.Active then
|
||
-- -- 添加进去
|
||
-- local Item = ArchiveTable.EasterEggs[EasterIndex]
|
||
-- if Item ~= nil then
|
||
-- local Type = Item.Reward.Type
|
||
-- if Type ~= nil then
|
||
-- if self.NewGameInitialData[Type] == nil then
|
||
-- self.NewGameInitialData[Type] = ArchiveTable.EasterEggs[EasterIndex].Reward.Value
|
||
-- else
|
||
-- self.NewGameInitialData[Type] = self.NewGameInitialData[Type] + ArchiveTable.EasterEggs[EasterIndex].Reward.Value
|
||
-- end
|
||
-- --print(string.format("[BP_PlayerState:LoadNewGameInitialData] Type = " .. tostring(Type)))
|
||
-- end
|
||
-- end
|
||
-- end
|
||
--end
|
||
|
||
log_tree("[BP_PlayerState:LoadNewGameInitialData] End self.NewGameInitialData = ", self.NewGameInitialData);
|
||
|
||
-- 应用到 Attributes[Base] 中
|
||
--self.NewGameInitialData = OutTable
|
||
|
||
print(string.format('[BP_PlayerState:LoadNewGameInitialData] 应用到数据:'))
|
||
log_tree("NewGameInitialData = ", self.NewGameInitialData)
|
||
end
|
||
|
||
function BP_PlayerState:GetGameTimes()
|
||
local GameTimes = 0
|
||
local ArchiveData = self.ArchiveData
|
||
if ArchiveData then
|
||
local ArchivedGameTimes = ArchiveData.GameTimes
|
||
GameTimes = ArchivedGameTimes ~= nil and ArchivedGameTimes or 0
|
||
end
|
||
|
||
return GameTimes
|
||
end
|
||
|
||
function BP_PlayerState:GetNeedTriggerForceGuide()
|
||
local SavedArchiveData = self.SavedArchiveData
|
||
local PlayedGames = SavedArchiveData.PlayedGames
|
||
local MaxDifficulty = 0
|
||
for Difficulty, Times in pairs(PlayedGames) do
|
||
if Times ~= nil and Times > 0 then
|
||
if Difficulty >= 5 then
|
||
return false
|
||
else
|
||
if Difficulty > MaxDifficulty then
|
||
MaxDifficulty = Difficulty
|
||
end
|
||
end
|
||
end
|
||
end
|
||
-- return self:GetGameTimes() <= 100
|
||
local GameDifficulty = UGCGameSystem.GameState.GameDifficulty
|
||
return false
|
||
-- return GameDifficulty ~= nil and MaxDifficulty < 5 and GameDifficulty > 0 and GameDifficulty <= 2
|
||
end
|
||
|
||
-- 初始化存档数据(从 NewGameInitialData 加载到 Attributes[Base] )
|
||
function BP_PlayerState:InitData()
|
||
print(string.format('[BP_PlayerState:InitData] 开始往 Attributes 中写入数据'))
|
||
|
||
for i, v in pairs(self.NewGameInitialData) do
|
||
if self.Attributes[AttributeType.Base][i] ~= nil then
|
||
self.Attributes[AttributeType.Base][i] = self.Attributes[AttributeType.Base][i] + v
|
||
else
|
||
local EnName = GlobalConfigs.AttributeNameTable[i]
|
||
if EnName ~= nil then
|
||
if self.Attributes[AttributeType.Base][EnName] == nil then
|
||
self.Attributes[AttributeType.Base][EnName] = v
|
||
else
|
||
self.Attributes[AttributeType.Base][EnName] = self.Attributes[AttributeType.Base][EnName] + v
|
||
end
|
||
else
|
||
self.AppendAttribute[i] = v
|
||
print(string.format('[BP_PlayerState:InitData] 无法找到名为 %s 的属性,请检查', i))
|
||
end
|
||
end
|
||
end
|
||
|
||
print(string.format('[BP_PlayerState:InitData] 玩家:%d', self.UID))
|
||
log_tree("Attributes = ", self.Attributes)
|
||
|
||
-- 下面是检查其他不在 GlobalConfigs 中的一些属性,然后依次实现即可,比如 中级配件 这种
|
||
self:HandleOtherAttribute()
|
||
end
|
||
|
||
function BP_PlayerState:HandleOtherAttribute()
|
||
log_tree("[BP_PlayerState:HandleOtherAttribute] self.AppendAttribute = ", self.AppendAttribute);
|
||
for i, v in pairs(self.AppendAttribute) do
|
||
if i == '初始金币' then
|
||
self.CoinPoint.Current = self.CoinPoint.Current + v
|
||
self.CoinPoint.Total = self.CoinPoint.Total + v;
|
||
elseif i == '初始科技点' then
|
||
self.KillPoint.Current = self.KillPoint.Current + v;
|
||
self.KillPoint.Total = self.KillPoint.Total + v;
|
||
-- @Test 简化
|
||
--elseif i == '初级配件' then
|
||
-- self:GiveArchiveInitItem(EDropItemSet.WeaponParts, EQualityType.Primary)
|
||
--elseif i == '中级配件' then
|
||
-- self:GiveArchiveInitItem(EDropItemSet.WeaponParts, EQualityType.Middle)
|
||
--elseif i == '高级配件' then
|
||
-- self:GiveArchiveInitItem(EDropItemSet.WeaponParts, EQualityType.Senior)
|
||
elseif i == '初级技能' then
|
||
if type(v) == 'number' then
|
||
for c = 1, v do
|
||
self:GiveArchiveInitItem(EDropItemSet.SkillBooks, EQualityType.Primary, 1)
|
||
end
|
||
else
|
||
self:GiveArchiveInitItem(EDropItemSet.SkillBooks, EQualityType.Primary, 1)
|
||
end
|
||
elseif i == '中级技能' then
|
||
if type(v) == 'number' then
|
||
for c = 1, v do
|
||
self:GiveArchiveInitItem(EDropItemSet.SkillBooks, EQualityType.Middle, 1)
|
||
end
|
||
else
|
||
self:GiveArchiveInitItem(EDropItemSet.SkillBooks, EQualityType.Middle, 1)
|
||
end
|
||
elseif i == '高级技能' then
|
||
if type(v) == 'number' then
|
||
for c = 1, v do
|
||
self:GiveArchiveInitItem(EDropItemSet.SkillBooks, EQualityType.Senior, 1)
|
||
end
|
||
else
|
||
self:GiveArchiveInitItem(EDropItemSet.SkillBooks, EQualityType.Senior, 1)
|
||
end
|
||
--elseif i == "高级抽奖金币消耗%" then
|
||
|
||
elseif i == "初始经验" then
|
||
-- 添加初始经验
|
||
self:AddExp(v)
|
||
else
|
||
print(string.format("[BP_PlayerState:HandleOtherAttribute] 此时选项是 %s, 值是 %s", tostring(i), tostring(v)));
|
||
end
|
||
end
|
||
end
|
||
|
||
function BP_PlayerState:GiveArchiveInitItem(InType, InQuality, InCount)
|
||
local ItemId = 0
|
||
if InType == EDropItemSet.WeaponParts then
|
||
local RanNum1 = math.random(1, 5) -- 配件种类
|
||
local RandNum2 = math.random(1, 6) -- 武器
|
||
ItemId = 10000 + RanNum1 * 1000 + RandNum2 * 100 + (InQuality + 1) * 10
|
||
elseif InType == EDropItemSet.SkillBooks then
|
||
local RanNum = math.random(9, 32)
|
||
ItemId = 20000 + RanNum * 100 + (InQuality + 1) * 10
|
||
end
|
||
|
||
-- 加到背包
|
||
local PlayerController = UGCGameSystem.GetPlayerControllerByPlayerKey(self.PlayerKey)
|
||
PlayerController:UpdateItemMap(ItemId, InCount)
|
||
end
|
||
|
||
function BP_PlayerState:TestAddStone()
|
||
local PlayerController = UGCGameSystem.GetPlayerControllerByPlayerKey(self.PlayerKey)
|
||
PlayerController:UpdateItemMap(31000, 100)
|
||
PlayerController:UpdateItemMap(32000, 100)
|
||
end
|
||
|
||
-- 重置除了基础属性其他属性
|
||
function BP_PlayerState:InitWeaponAttribute()
|
||
if self.Attributes[AttributeType.Weapon] ~= nil then
|
||
for i, v in pairs(self.Attributes[AttributeType.Weapon]) do
|
||
self.Attributes[AttributeType.Weapon][i] = 0
|
||
self.Attributes[AttributeType.WeaponSpecial][i] = 0
|
||
end
|
||
end
|
||
end
|
||
|
||
function BP_PlayerState:InitChallengeMonsterTime(InTime)
|
||
for k, TargetMonsterInfo in pairs(Tables.ChallengeInfo) do
|
||
self.ChallengeMonsterTime[k] = {LastChallengeTime = InTime, CoolingTime = TargetMonsterInfo.CoolingTime}
|
||
end
|
||
end
|
||
|
||
-- Server
|
||
function BP_PlayerState:OnWeaponAttributeChanged(InWeaponId)
|
||
-- 在这里判断是不是当前 Weapon,如果不是可以直接不更新
|
||
UE.Log("[BP_PlayerState:OnWeaponAttributeChanged] 开始更新玩家属性表")
|
||
local PlayerPawn = UGCGameSystem.GetPlayerPawnByPlayerKey(self.PlayerKey)
|
||
|
||
local WC = PlayerPawn:GetWeaponComponent()
|
||
if WC == nil then
|
||
UE.Log("[BP_PlayerState:OnWeaponAttributeChanged] 检查一下 WC")
|
||
return
|
||
end
|
||
|
||
local CurrWeaponId = WC.CurrentWeaponId
|
||
local Data = GameDataManager.GetWeaponConstructDataByID(CurrWeaponId)
|
||
if Data == nil then
|
||
UE.Log("[BP_PlayerState:OnWeaponAttributeChanged] Data is nil")
|
||
return
|
||
end
|
||
|
||
--要更新的不是当前武器,所以忽略
|
||
if InWeaponId ~= CurrWeaponId then
|
||
return
|
||
end
|
||
|
||
-- 清空属性表
|
||
|
||
self:InitWeaponAttribute()
|
||
|
||
local OutTable, SpecialItems = --[[WC:GetOutProps()]] {}, {}
|
||
|
||
-- 是否要刷新射速
|
||
local bShootRefresh = false
|
||
|
||
for i = 1, #OutTable do
|
||
local SingleVal = OutTable[i]
|
||
|
||
if SingleVal == nil then
|
||
UE.Log("[BP_PlayerState:OnWeaponAttributeChanged] 里面的值为空,请检查")
|
||
else
|
||
local Index = GlobalConfigs.AttributeNameTable[SingleVal.Type]
|
||
if not bShootRefresh then
|
||
if SingleVal.Type ~= nil then
|
||
bShootRefresh = string.find(SingleVal.Type, '射速') ~= -1
|
||
else
|
||
UE.Log("[BP_PlayerState:OnWeaponAttributeChanged] 此时属性是 nil")
|
||
end
|
||
end
|
||
|
||
-- 这些是基础属性
|
||
if Index ~= nil then
|
||
-- 添加到武器属性上
|
||
self.Attributes[AttributeType.Weapon][Index] = SingleVal.Value + self.Attributes[AttributeType.Weapon][Index]
|
||
print(string.format("[BP_PlayerState:OnWeaponAttributeChanged] Value = %s", tostring(self.Attributes[AttributeType.Weapon][Index])))
|
||
else
|
||
-- 检查是否是 Special
|
||
if SingleVal.Unit == 'Special' then
|
||
print(string.format('[BP_PlayerState:OnWeaponAttributeChanged] 当前是特殊词条'))
|
||
self.Attributes[AttributeType.WeaponSpecial][SingleVal.Type] = SingleVal.Value
|
||
else
|
||
|
||
end
|
||
if SingleVal.Type ~= nil then
|
||
if math.type(SingleVal.Value) == 'integer' then
|
||
UE.Log("[BP_PlayerState:OnWeaponAttributeChanged] 未设置:Key: %s, Value = %d", SingleVal.Type, SingleVal.Value)
|
||
elseif math.type(SingleVal.Value) == 'float' then
|
||
UE.Log("[BP_PlayerState:OnWeaponAttributeChanged] 未设置:Key: %s, Value = %f", SingleVal.Type, SingleVal.Value)
|
||
else
|
||
UE.Log("[BP_PlayerState:OnWeaponAttributeChanged] 值为空,请检查一下")
|
||
end
|
||
else
|
||
UE.Log("[BP_PlayerState:OnWeaponAttributeChanged] Find Index == nil")
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
local Val = 0
|
||
for _, v in pairs(self.Attributes) do
|
||
Val = Val + v.Base_AttackRange
|
||
end
|
||
UE.Log("[BP_PlayerState:OnWeaponAttributeChanged] 此时额外攻击距离是 %s", tostring(Val))
|
||
self.AttackRange = Val > 0 and Val or 0
|
||
|
||
if bShootRefresh then
|
||
EventSystem:SendEvent(EventType.RefreshShoot)
|
||
end
|
||
|
||
if table.getCount(SpecialItems) > 0 then
|
||
self:DealWithSpecialItems(SpecialItems)
|
||
else
|
||
print(string.format("[BP_PlayerState:OnWeaponAttributeChanged] 当前没有特殊的配件"))
|
||
end
|
||
|
||
self:PostChangedProps();
|
||
|
||
self:ApplyAttributes();
|
||
end
|
||
|
||
function BP_PlayerState:PostChangedProps()
|
||
-- 每1%的暴击伤害%加成会提高3%的射击伤害%
|
||
if self:IsCurrentWeaponHasItem(14540) then
|
||
local TotalAttack = 0
|
||
for _, v in pairs(self.Attributes) do
|
||
TotalAttack = v.Bonus_CriticalAttack + TotalAttack
|
||
end
|
||
self.Attributes[AttributeType.WeaponSpecial].Bonus_CriticalAttack = TotalAttack * 3
|
||
else
|
||
self.Attributes[AttributeType.WeaponSpecial].Bonus_CriticalAttack = 0
|
||
end
|
||
|
||
if self:IsCurrentWeaponHasItem(15640) then
|
||
local TotalAttack = 0
|
||
for _, v in pairs(self.Attributes) do
|
||
TotalAttack = v.Bonus_FireAttack + TotalAttack
|
||
end
|
||
self.Attributes[AttributeType.WeaponSpecial].Adv_CriticalAttack = TotalAttack * 3
|
||
else
|
||
self.Attributes[AttributeType.WeaponSpecial].Adv_CriticalAttack = 0
|
||
end
|
||
end
|
||
|
||
function BP_PlayerState:DealWithSpecialItems(InItems)
|
||
print(string.format("[BP_PlayerState:DealWithSpecialItems] 处理特殊物品"))
|
||
-- 此时里面是有数据的
|
||
-- 首先跟之前的进行比较,观察是否有移除或者添加的 Item,找出交集,然后分别对比前后
|
||
local SameItems = {}
|
||
local NeedRemoveItems = {}
|
||
local NeedAddItems = {}
|
||
|
||
local NewItems = {}
|
||
local OldItems = {}
|
||
|
||
for i = 1, table.getCount(InItems) do
|
||
NewItems[InItems[i].ItemId] = 1
|
||
print(string.format("[BP_PlayerState:DealWithSpecialItems] Item Id = %d", InItems[i].ItemId))
|
||
end
|
||
for i = 1, table.getCount(self.LastSpecialItems) do
|
||
OldItems[self.LastSpecialItems[i]] = 1
|
||
end
|
||
|
||
for i, v in pairs(NewItems) do
|
||
if OldItems[i] == 1 then
|
||
-- 说明这是公共的
|
||
SameItems[i] = 1
|
||
else
|
||
-- 说明是需要添加的
|
||
NeedAddItems[i] = 1
|
||
end
|
||
end
|
||
for i, v in pairs(OldItems) do
|
||
if OldItems[i] == nil then
|
||
-- 说明是需要移除的
|
||
NeedRemoveItems[i] = 1
|
||
end
|
||
end
|
||
|
||
self.LastSpecialItems = InItems
|
||
|
||
if table.getCount(SameItems) then
|
||
for i, v in pairs(SameItems) do
|
||
print(string.format("[BP_PlayerState:DealWithSpecialItems] 相同的物品:%d", i))
|
||
end
|
||
end
|
||
|
||
if table.getCount(NeedAddItems) > 0 then
|
||
for i, v in pairs(NeedAddItems) do
|
||
print(string.format("[BP_PlayerState:DealWithSpecialItems] 需要添加的物品:%d", i))
|
||
end
|
||
end
|
||
|
||
if table.getCount(NeedRemoveItems) > 0 then
|
||
for i, v in pairs(NeedRemoveItems) do
|
||
print(string.format("[BP_PlayerState:DealWithSpecialItems] 需要移除的物品:%d", i))
|
||
end
|
||
end
|
||
|
||
if table.getCount(NeedAddItems) > 0 then
|
||
self:AddSpecialItems(NeedAddItems)
|
||
end
|
||
if table.getCount(NeedRemoveItems) > 0 then
|
||
self:RemoveSpecialItems(NeedRemoveItems)
|
||
end
|
||
end
|
||
|
||
-- {id = 1}
|
||
function BP_PlayerState:AddSpecialItems(InItems)
|
||
local PlayerPawn = UGCGameSystem.GetPlayerPawnByPlayerKey(self.PlayerKey)
|
||
print(string.format("[BP_PlayerState:AddSpecialItems] 添加特殊物品"))
|
||
for i, v in pairs(InItems) do
|
||
print(string.format("[BP_PlayerState:AddSpecialItems] 特殊物品:%d", i))
|
||
local Cond = DropItemMap.SpecialFittingProperties[i][1].Condition
|
||
|
||
self.SpecialItemTimerHandles[Cond][i] = {
|
||
Times = 0,
|
||
LastTime = 0,
|
||
}
|
||
if Cond == '击败' then
|
||
|
||
elseif Cond == '每秒' then
|
||
|
||
elseif Cond == '射击' then
|
||
|
||
--self:Special_RemoveKillCount(i)
|
||
elseif Cond == '射击%' then
|
||
|
||
elseif Cond == '周期' then
|
||
|
||
elseif Cond == '固定' then
|
||
|
||
end
|
||
end
|
||
end
|
||
|
||
-- {id = 1}
|
||
function BP_PlayerState:RemoveSpecialItems(InItems)
|
||
for i, v in pairs(InItems) do
|
||
local Cond = DropItemMap.SpecialFittingProperties[i][1].Condition
|
||
self.SpecialItemTimerHandles[Cond][i] = {
|
||
Times = 0,
|
||
LastTime = 0,
|
||
}
|
||
if Cond == '击败' then
|
||
self:Special_RemoveKillCount(i)
|
||
elseif Cond == '每秒' then
|
||
self:Special_RemoveKillCount(i)
|
||
elseif Cond == '射击' then
|
||
self:Special_RemoveKillCount(i)
|
||
elseif Cond == '射击%' then
|
||
|
||
elseif Cond == '周期' then
|
||
|
||
elseif Cond == '固定' then
|
||
|
||
end
|
||
end
|
||
end
|
||
|
||
--测试打印所有属性
|
||
function BP_PlayerState:PrintAllAttributes()
|
||
UE.Log("[BP_PlayerState:PrintAllAttributes] 开始打印 Attributes")
|
||
--玩家的普通属性
|
||
for _, v in pairs(self.Attributes) do
|
||
print(string.format('[BP_PlayerState:PrintAllAttributes] Id = %d', _))
|
||
for j, k in pairs(v) do
|
||
if math.type(k) == 'integer' then
|
||
UE.Log('%s = %d', j, k)
|
||
elseif math.type(k) == 'float' then
|
||
UE.Log('%s = %f', j, k)
|
||
end
|
||
end
|
||
end
|
||
UE.Log("[BP_PlayerState:PrintAllAttributes] 结束打印 Attributes")
|
||
end
|
||
|
||
-- 应用玩家最大生命值和最大能量值属性
|
||
function BP_PlayerState:ApplyAttributes()
|
||
print(string.format('[BP_PlayerState:ApplyAttributes] 执行方法'))
|
||
local PlayerPawn = UGCGameSystem.GetPlayerPawnByPlayerKey(self.PlayerKey)
|
||
|
||
--self:PrintAllAttributes()
|
||
local TheHP = 0
|
||
local TheEnergy = 0
|
||
for _, v in pairs(self.Attributes) do
|
||
TheHP = TheHP + v.Base_MaxHP
|
||
TheEnergy = TheEnergy + v.Base_MaxEnergy
|
||
end
|
||
UE.Log("[BP_PlayerState:ApplyAttributes] PlayerKey = %d, MaxHealth = %f, MaxEnergy = %f", self.PlayerKey, TheHP, TheEnergy)
|
||
|
||
PlayerPawn:SetMaxHealth(TheHP)
|
||
PlayerPawn:SetMaxEnergy(TheEnergy)
|
||
end
|
||
|
||
-- 武器属性不用管
|
||
function BP_PlayerState:GrowthAttributes()
|
||
local GrowthHp = 0
|
||
|
||
-- 直接读取所有的 GrowthHp
|
||
for _, v in pairs(self.Attributes) do
|
||
GrowthHp = v.Growth_MaxHP * (1 + v.Bonus_MaxHP) + GrowthHp
|
||
end
|
||
|
||
if GrowthHp > 0 then
|
||
self.Attributes[AttributeType.Base].Base_MaxHP = self.Attributes[AttributeType.Base].Base_MaxHP + GrowthHp
|
||
local PlayerPawn = UGCGameSystem.GetPlayerPawnByPlayerKey(self.PlayerKey)
|
||
local Temp = 0
|
||
for _, v in pairs(self.Attributes) do
|
||
Temp = Temp + v.Base_MaxHP
|
||
end
|
||
PlayerPawn:SetMaxHealth(Temp)
|
||
end
|
||
|
||
for _, v in pairs(self.Attributes) do
|
||
v.Base_Attack = v.Base_Attack + v.Growth_Attack * (1 + v.Bonus_Attack)
|
||
end
|
||
end
|
||
|
||
-- 武器属性不用管
|
||
function BP_PlayerState:GrowthKillPoint()
|
||
local Temp = 0
|
||
for _, v in pairs(self.Attributes) do
|
||
Temp = Temp + v.Growth_KillPoint * (1 + v.Eco_KillPoint)
|
||
end
|
||
self.KillPoint.Current = self.KillPoint.Current + Temp
|
||
self.KillPoint.Total = self.KillPoint.Total + Temp
|
||
|
||
ArchiveTable.Funcs[ArchiveTable.ArchiveType.EasterEggs](self, 6)
|
||
end
|
||
|
||
-- 战斗力公式(没啥用,就仅显示)
|
||
function BP_PlayerState:RefreshCombatPoint()
|
||
local CombatPoint = 0
|
||
for _, v in pairs(self.Attributes) do
|
||
CombatPoint = CombatPoint +
|
||
v.Base_MaxHP / 250 + v.Base_Attack / 50 + v.Base_Defence / 4 + v.Adv_DefencePenetration * 3
|
||
+ v.Adv_CriticalAttackRate * 20000 + v.Adv_CriticalAttack * 150 + v.Adv_FireAttack * 225 + v.Adv_DefencePenetrationPercent * 50000
|
||
+ v.Adv_AdditionalAttack * 30000 + v.Adv_FinalAttack * 30000 + v.Growth_MaxHP * 500 + v.Growth_Attack * 2500
|
||
+ v.Base_AttackSpeed * 2000 + v.Bonus_Attack * 5000 + v.Bonus_MaxHP * 10000 + v.Bonus_Defence * 5000
|
||
+ v.Bonus_DamageReduction * 200000 + v.Eco_CoinPoint * 2000 + v.Eco_KillPoint * 2000 + v.Eco_Exp * 3000
|
||
+ v.Eco_DropRate * 2000 + v.Bonus_CriticalAttack * 100000 + v.Bonus_FireAttack * 150000 + v.Growth_Kill_MaxHP * 1000 + v.Growth_Kill_Attack * 5000
|
||
end
|
||
self.CombatPoint = math.ceil(CombatPoint)
|
||
EventSystem:SendEvent(EventType.ServerOnCombatPointChanged, self.PlayerKey, self.CombatPoint)
|
||
end
|
||
|
||
-- 玩家造成伤害公式,InVal是反弹伤害
|
||
function BP_PlayerState:MakeDamage(InEnemy, InVal)
|
||
--这个是敌人受到伤害加成
|
||
local EnemyAppendDamage = self:GetAdditionDamage()
|
||
local Damage = 0
|
||
for _, v in pairs(self.Attributes) do
|
||
Damage = Damage + (v.Base_Attack * (1 + v.Bonus_Attack)) * (1 + v.Adv_FireAttack * (1 + v.Bonus_FireAttack)
|
||
+ v.Adv_AdditionalAttack) * (1 + EnemyAppendDamage) * (1 + v.Adv_FinalAttack)
|
||
end
|
||
|
||
-- 每射击5次,下次射击必定暴击
|
||
if self:IsCurrentWeaponHasItem(11140) then
|
||
local TheId = 11140
|
||
local AttackTimes = DropItemMap.SpecialFittingProperties[TheId][1].Times
|
||
if self.SpecialThings[TheId] == nil then
|
||
self.SpecialThings[TheId] = {}
|
||
end
|
||
if self.SpecialThings[TheId].Times ~= nil then
|
||
if self.SpecialThings[TheId].Times < AttackTimes then
|
||
self.SpecialThings[TheId].Times = self.SpecialThings[TheId].Times + 1
|
||
self.SpecialThings[TheId].CertainCriticalAttack = true
|
||
else
|
||
self.SpecialThings[TheId].Times = self.SpecialThings[TheId].Times - AttackTimes
|
||
self.SpecialThings[TheId].CertainCriticalAttack = false
|
||
-- 让下次射击暴击
|
||
end
|
||
else
|
||
self.SpecialThings[TheId].Times = 1
|
||
self.SpecialThings[TheId].CertainCriticalAttack = false
|
||
end
|
||
end
|
||
|
||
--每次射击有25%概率造成2次伤害
|
||
local Val = 1
|
||
if self:IsCurrentWeaponHasItem(11440) and math.RandomValue(25) then
|
||
Val = 2
|
||
end
|
||
|
||
-- 射击有5%概率使敌人防御值降低30%,持续5秒
|
||
local TheId1 = 14240
|
||
if self:IsCurrentWeaponHasItem(TheId1) then
|
||
local ServerTime = KismetSystemLibrary.GetGameTimeInSeconds(self)
|
||
if self.SpecialThings[TheId1] == nil then
|
||
self.SpecialThings[TheId1] = {}
|
||
self.SpecialThings[TheId1].ServerTime = ServerTime
|
||
self.SpecialThings[TheId1].LimitServerTime = ServerTime
|
||
else
|
||
local LimitServerTime = self.SpecialThings[TheId1].ServerTime
|
||
if self.SpecialThings[TheId1].ServerTime > LimitServerTime then
|
||
if math.RandomValue(0.01 * DropItemMap.SpecialFittingProperties[TheId1][1].Probability) then
|
||
InEnemy:SetDefenseScale(DropItemMap.SpecialFittingProperties[TheId1][1].Benefit.Value)
|
||
self.SpecialThings[TheId1].LimitServerTime = DropItemMap.SpecialFittingProperties[TheId1][1].CoolDown + ServerTime
|
||
end
|
||
else
|
||
self.SpecialThings[TheId1].ServerTime = ServerTime
|
||
end
|
||
end
|
||
end
|
||
|
||
if self:OnCriticalAttack() then
|
||
local Multiply = 0
|
||
for _, v in pairs(self.Attributes) do
|
||
Multiply = Multiply + (1 + v.Adv_CriticalAttack) * (1 + v.Bonus_CriticalAttack)
|
||
end
|
||
Damage = Damage * Multiply
|
||
end
|
||
|
||
if InVal == nil then
|
||
InVal = 0
|
||
end
|
||
|
||
return Damage * Val + InVal
|
||
end
|
||
|
||
-- private 计算是否暴击
|
||
function BP_PlayerState:OnCriticalAttack()
|
||
local TheId = 11140
|
||
local ShouldCriticalAttack = self.SpecialThings[TheId] ~= nil and self.SpecialThings[TheId].CertainCriticalAttack or false
|
||
local CriticalAttackPercent = 0
|
||
for _, v in pairs(self.Attributes) do
|
||
CriticalAttackPercent = CriticalAttackPercent + v.Adv_CriticalAttackRate
|
||
end
|
||
local RandomVal = math.random()
|
||
return RandomVal <= CriticalAttackPercent or ShouldCriticalAttack
|
||
end
|
||
|
||
-- 玩家防御穿透
|
||
function BP_PlayerState:DefencePenetrate()
|
||
local Temp = 0
|
||
for _, v in pairs(self.Attributes) do
|
||
Temp = Temp + v.Adv_DefencePenetration
|
||
end
|
||
return Temp
|
||
end
|
||
|
||
-- 玩家产生的伤害加成
|
||
function BP_PlayerState:GetAdditionDamage()
|
||
return 0
|
||
end
|
||
|
||
-- 减伤公式
|
||
function BP_PlayerState:InjuryReduction(InEnemy)
|
||
-- local EnemyDefence = InEnemy:GetDefense()
|
||
local EnemyDefencePercent = InEnemy.DamageReductionPercentage
|
||
-- 伤害减免
|
||
local Temp = 0
|
||
for i, v in pairs(self.Attributes) do
|
||
Temp = Temp + (v.Base_Defence * (1 + v.Bonus_Defence) - 0) * (1 - EnemyDefencePercent)
|
||
end
|
||
return Temp
|
||
end
|
||
|
||
-- 玩家收到的伤害
|
||
function BP_PlayerState:GetDamage(InEnemy, InNum)
|
||
local EnemyDamage = self:InjuryReduction(InEnemy)
|
||
local Temp = 0
|
||
for _, v in pairs(self.Attributes) do
|
||
Temp = Temp + v.Bonus_DamageReduction
|
||
end
|
||
local Res = InNum * (1 - (EnemyDamage / (EnemyDamage + 1000))) * (1 - Temp)
|
||
return Res
|
||
end
|
||
|
||
--反弹伤害
|
||
function BP_PlayerState:GetReverseDamage(InEnemy)
|
||
local Ir = self:InjuryReduction(InEnemy)
|
||
return self:MakeDamage(InEnemy) * (1 - Ir)
|
||
end
|
||
|
||
-- 根据数值进行 Reverse Damage
|
||
function BP_PlayerState:GetReverseDamage(InEnemy, InNum)
|
||
local Ir = self:InjuryReduction(InEnemy)
|
||
local Damage = 0
|
||
local DamagePercent = 0
|
||
|
||
-- 计算反弹伤害
|
||
for i, v in pairs(self.Attributes) do
|
||
Damage = v.Base_ReboundDamage + Damage
|
||
DamagePercent = v.Base_ReboundDamagePercent + DamagePercent
|
||
end
|
||
|
||
return self:MakeDamage(InEnemy, Damage + InNum * DamagePercent) * (1 - Ir)
|
||
end
|
||
|
||
-- 处理护盾,返回具体受到的伤害
|
||
function BP_PlayerState:DealShield(InDamage)
|
||
if self.Attributes[AttributeType.Base].Base_Shield > InDamage then
|
||
self.Attributes[AttributeType.Base].Base_Shield = self.Attributes[AttributeType.Base].Base_Shield - InDamage
|
||
return 0
|
||
else
|
||
local Ret = InDamage - self.Attributes[AttributeType.Base].Base_Shield
|
||
self.Attributes[AttributeType.Base].Base_Shield = 0
|
||
return Ret
|
||
end
|
||
end
|
||
|
||
--吸血
|
||
function BP_PlayerState:SuckBlood(InDamage)
|
||
local VampVal = 0
|
||
for _, v in pairs(self.Attributes) do
|
||
VampVal = VampVal + v.Base_Vamp
|
||
end
|
||
return InDamage * (1 - 1 / (1 + VampVal))
|
||
end
|
||
|
||
-- 闪避
|
||
function BP_PlayerState:Dodge()
|
||
local Rate = 0
|
||
for _, v in pairs(self.Attributes) do
|
||
Rate = Rate + v.Base_EvadeRate
|
||
end
|
||
return 1 - 1 / (1 + Rate)
|
||
end
|
||
|
||
-- 韧性
|
||
function BP_PlayerState:Tenacity()
|
||
local Rate = 0
|
||
for _, v in pairs(self.Attributes) do
|
||
Rate = Rate + v.Base_Toughness
|
||
end
|
||
return 1 - Rate
|
||
end
|
||
|
||
-- 每秒射速
|
||
function BP_PlayerState:ShootTimeEverSecond()
|
||
local AttackSpeed, Rate = 0, 0
|
||
for _, v in pairs(self.Attributes) do
|
||
Rate = Rate + v.Base_AttackIntervalReduction
|
||
AttackSpeed = AttackSpeed + v.Base_AttackSpeed
|
||
end
|
||
return AttackSpeed / Rate
|
||
end
|
||
|
||
-- 每秒生命值
|
||
function BP_PlayerState:RecoverPlayerPawn()
|
||
local PlayerPawn = UGCGameSystem.GetPlayerPawnByPlayerKey(self.PlayerKey)
|
||
local RecoverHp, RecoverHpPercent, bre, brep = 0, 0, 0, 0
|
||
for _, v in pairs(self.Attributes) do
|
||
RecoverHp = RecoverHp + v.Base_RecoverHP
|
||
RecoverHpPercent = RecoverHpPercent + v.Base_RecoverHPPercent
|
||
bre = bre + v.Base_RecoverEnergy
|
||
brep = brep + v.Base_RecoverEnergyPercent
|
||
end
|
||
UE.Log("[BP_PlayerState:RecoverPlayerPawn] PlayerKey: %d, Recover HP = %s, Recover HP Percent = %s", self.PlayerKey, tostring(RecoverHp), tostring(RecoverHpPercent))
|
||
|
||
if UE.IsValid(PlayerPawn) then
|
||
self:RecoverPlayerCurHP(PlayerPawn, RecoverHp, RecoverHpPercent)
|
||
self:RecoverPlayerCurEnergy(PlayerPawn, bre, brep)
|
||
end
|
||
end
|
||
|
||
-- 每秒刷新的数据
|
||
function BP_PlayerState:AttributeAdditionPerSecond()
|
||
--每秒杀敌点
|
||
local val, Shield = 0, 0
|
||
for _, v in pairs(self.Attributes) do
|
||
val = val + v.Growth_KillPoint
|
||
Shield = Shield + v.Growth_Shield
|
||
end
|
||
if val > 0 then
|
||
self.KillPoint.Current = math.ceil(self.KillPoint.Current + val)
|
||
self.KillPoint.Total = (self.KillPoint.Total + val)
|
||
end
|
||
|
||
self:Special_AddPerSecondProp(12440, 0)
|
||
self:Special_AddPerSecondProp(12540, 0)
|
||
|
||
-- 查看是否需要护盾,该值是 %
|
||
if Shield > 0 then
|
||
self:PropShield('Shield', Shield)
|
||
end
|
||
|
||
-- 每隔10秒,进入嗜血状态,该状态下吸血%达到100%,持续2秒
|
||
if self:IsCurrentWeaponHasItem(11340) then
|
||
local TheId = 11340
|
||
if self.SpecialThings[TheId] == nil then
|
||
self.SpecialThings[TheId] = {}
|
||
self.SpecialThings[TheId].CurrentTime = 1
|
||
else
|
||
self.SpecialThings[TheId].CurrentTime = self.SpecialThings[TheId].CurrentTime + 1
|
||
if self.SpecialThings[TheId].CurrentTime >= 10 then
|
||
-- 此时启动即可
|
||
self.Attributes[AttributeType.WeaponSpecial].Base_Vamp = 1
|
||
EventSystem.SetTimer(self, function()
|
||
self.Attributes[AttributeType.WeaponSpecial].Base_Vamp = 0
|
||
end, 2)
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
-- 此处 Id 是护盾的意思
|
||
function BP_PlayerState:PropShield(InId, InValue)
|
||
if self.SpecialThings[InId] == nil then
|
||
self.SpecialThings[InId] = 0
|
||
end
|
||
if self.SpecialThings[InId] < 10 then
|
||
self.SpecialThings[InId] = self.SpecialThings[InId] + 1
|
||
else
|
||
local Pawn = UGCGameSystem.GetPlayerPawnByPlayerKey(self.PlayerKey)
|
||
local MaxHP = UGCPawnAttrSystem.GetHealthMax(Pawn)
|
||
local AppendHealth = InValue * MaxHP
|
||
self.Attributes[AttributeType.Base].Base_Shield = self.Attributes[AttributeType.Base].Base_Shield + AppendHealth
|
||
end
|
||
end
|
||
|
||
-- 这是添加每秒的东西
|
||
function BP_PlayerState:Special_AddPerSecondProp(InId, InTime)
|
||
if self:IsCurrentWeaponHasItem(InId) then
|
||
if self.SpecialThings[InId] == nil then
|
||
self.SpecialThings[InId] = 0
|
||
end
|
||
if self.SpecialThings[InId] < InTime then
|
||
self.SpecialThings[InId] = self.SpecialThings[InId] + 1
|
||
else
|
||
local Val = DropItemMap.SpecialFittingProperties[InId][1].Benefit
|
||
self:AddAttribute(Val.Type, Val.Value, true)
|
||
self.SpecialThings[InId] = 0
|
||
end
|
||
end
|
||
end
|
||
|
||
function BP_PlayerState:GetDroppingRate()
|
||
local DropRate = 0
|
||
for i, v in pairs(self.Attributes) do
|
||
DropRate = DropRate + v.Eco_DropRate
|
||
end
|
||
return DropRate
|
||
end
|
||
|
||
function BP_PlayerState:RecoverPlayerCurHP(Pawn, Value, Percent)
|
||
Pawn:RecoverCurHP(Value, Percent)
|
||
end
|
||
|
||
function BP_PlayerState:RecoverPlayerCurEnergy(Pawn, Value, Percent)
|
||
Pawn:RecoverCurEnergy(Value, Percent)
|
||
end
|
||
|
||
--server 增加或者减少金币
|
||
function BP_PlayerState:UpdateCoinPoint(InDelta)
|
||
if self.CoinPoint.Current + InDelta < 0 then
|
||
return false
|
||
else
|
||
if InDelta > 0 then
|
||
self:AddCoinPoint(InDelta)
|
||
else
|
||
self.CoinPoint.Current = self.CoinPoint.Current + InDelta
|
||
end
|
||
return true
|
||
end
|
||
end
|
||
|
||
---生效范围:S,向上取整
|
||
function BP_PlayerState:AddCoinPointDirectly(InDelta)
|
||
if InDelta <= 0 then
|
||
return false
|
||
end
|
||
self.CoinPoint.Current = self.CoinPoint.Current + InDelta
|
||
self.CoinPoint.Current = math.ceil(self.CoinPoint.Current)
|
||
self.CoinPoint.Total = self.CoinPoint.Total + InDelta
|
||
|
||
ArchiveTable.Funcs[ArchiveTable.ArchiveType.EasterEggs](self, 1)
|
||
return true
|
||
end
|
||
|
||
---生效范围:S,向上取整
|
||
function BP_PlayerState:AddTechPointDirectly(InDelta)
|
||
local Delta = InDelta
|
||
self.KillPoint.Current = self.KillPoint.Current + Delta
|
||
self.KillPoint.Total = self.KillPoint.Total + Delta
|
||
self.KillPoint.Current = math.ceil(self.KillPoint.Current)
|
||
end
|
||
|
||
---生效范围:S,向上取整
|
||
function BP_PlayerState:AddCoinPoint(InDelta)
|
||
local Temp = 0
|
||
for i, v in pairs(self.Attributes) do
|
||
Temp = Temp + v.Eco_CoinPoint
|
||
end
|
||
local Delta = InDelta * (1 + Temp)
|
||
self.CoinPoint.Current = self.CoinPoint.Current + Delta
|
||
self.CoinPoint.Current = math.ceil(self.CoinPoint.Current)
|
||
self.CoinPoint.Total = self.CoinPoint.Total + Delta
|
||
|
||
-- 检查一下
|
||
ArchiveTable.Funcs[ArchiveTable.ArchiveType.EasterEggs](self, 1)
|
||
end
|
||
|
||
---生效范围:S,向上取整
|
||
function BP_PlayerState:AddKillPoint(InDelta)
|
||
local Temp = 0
|
||
for i, v in pairs(self.Attributes) do
|
||
Temp = Temp + v.Eco_KillPoint
|
||
end
|
||
local Delta = InDelta * (1 + Temp)
|
||
self.KillPoint.Current = self.KillPoint.Current + Delta
|
||
self.KillPoint.Total = self.KillPoint.Total + Delta
|
||
self.KillPoint.Current = math.ceil(self.KillPoint.Current)
|
||
end
|
||
|
||
-- 添加杀敌数(这个是真实数据)
|
||
function BP_PlayerState:AddKillCount()
|
||
self.KillCount.Total = self.KillCount.Total + 1
|
||
local Temp = 0
|
||
for i, v in pairs(self.Attributes) do
|
||
Temp = Temp + v.Growth_Kill_Attack
|
||
end
|
||
self.Attributes[AttributeType.Base].Base_Attack = self.Attributes[AttributeType.Base].Base_Attack + Temp
|
||
|
||
-- 执行 4 个
|
||
--local val = '击败'
|
||
--for i, v in pairs(self.SpecialItemTimerHandles[val]) do
|
||
-- print(string.format("[BP_PlayerState:AddKillCount] ItemID = %d", i))
|
||
-- self:Special_AddKillCount(val, i)
|
||
--end
|
||
end
|
||
|
||
--添加特殊词条 支持杀敌,这是那种有最大射击数的
|
||
function BP_PlayerState:Special_AddKillCount(InCond, InId)
|
||
--说明开启了
|
||
print(string.format("[BP_PlayerState:Special_AddKillCount] 执行到了"))
|
||
if self.SpecialItemTimerHandles[InCond] == nil then
|
||
return
|
||
end
|
||
local Prop = self.SpecialItemTimerHandles[InCond][InId]
|
||
local ServerTime = KismetSystemLibrary.GetGameTimeInSeconds(self)
|
||
|
||
-- 是否可以操作
|
||
local CanDoOperation = false
|
||
|
||
-- 说明当前还没开始
|
||
if Prop.Times == 0 then
|
||
-- 记录开始的时间
|
||
self.SpecialItemTimerHandles[InCond][InId].Times = 1
|
||
CanDoOperation = true
|
||
else
|
||
local LastTime = self.SpecialItemTimerHandles[InCond][InId].LastTime
|
||
local ContinueTime = DropItemMap.SpecialFittingProperties[InId][1].ContinueTime
|
||
if ContinueTime == nil or ContinueTime == -1 then
|
||
if Prop.Times <= DropItemMap.SpecialFittingProperties[InId][1].Times then
|
||
CanDoOperation = true
|
||
self.SpecialItemTimerHandles[InCond][InId].Times = Prop.Times + 1
|
||
end
|
||
else
|
||
if ServerTime - LastTime > ContinueTime then
|
||
--重置
|
||
self.SpecialItemTimerHandles[InCond][InId].Times = 0
|
||
self:Special_AddKillCount(InId)
|
||
else
|
||
if Prop.Times <= DropItemMap.SpecialFittingProperties[InId][1].Times then
|
||
CanDoOperation = true
|
||
self.SpecialItemTimerHandles[InCond][InId].Times = Prop.Times + 1
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
self.SpecialItemTimerHandles[InCond][InId].LastTime = ServerTime
|
||
|
||
if CanDoOperation then
|
||
local ChineseType = DropItemMap.SpecialFittingProperties[InId][1].Benefit.Type
|
||
-- 往这里面添加数据
|
||
print(string.format("[BP_PlayerState:Special_AddKillCount] Current Type = %s", ChineseType))
|
||
self.Attributes[AttributeType.WeaponSpecial][GlobalConfigs.AttributeNameTable[ChineseType]] = DropItemMap.SpecialFittingProperties[InId][1].Benefit.Value * self.SpecialItemTimerHandles[InCond][InId].Times
|
||
end
|
||
end
|
||
|
||
--移除特殊词条
|
||
function BP_PlayerState:Special_RemoveKillCount(InId)
|
||
local ChineseType = DropItemMap.SpecialFittingProperties[InId][1].Benefit.Type
|
||
self.Attributes[AttributeType.WeaponSpecial][GlobalConfigs.AttributeNameTable[ChineseType]] = 0
|
||
|
||
table.remove(self.SpecialItemTimerHandles, InId)
|
||
end
|
||
|
||
-- Server
|
||
function BP_PlayerState:SetLevelDirectly(NewLevel)
|
||
self.Level = NewLevel
|
||
ArchiveTable.Funcs[ArchiveTable.ArchiveType.EasterEggs](self, 7)
|
||
EventSystem:SendEvent(EventType.ServerOnLevelAndExpChanged, self.PlayerKey, self.Level, self.CurExp, self:GetNeedExpByLevel(self.Level))
|
||
end
|
||
|
||
-- Server
|
||
function BP_PlayerState:AddExp(InDelta)
|
||
-- 判断当前 Exp,改变当前传入的值
|
||
if InDelta < 0 then
|
||
return
|
||
end
|
||
|
||
-- 限制一下最高等级
|
||
if self.Level >= 60 then
|
||
return
|
||
end
|
||
|
||
-- 需要检查一下该值的变化
|
||
if self.BreachInfo.NeedBreach then
|
||
return
|
||
end
|
||
|
||
-- 数值
|
||
local Temp = 0
|
||
for _, v in pairs(self.Attributes) do
|
||
Temp = Temp + v.Eco_Exp
|
||
end
|
||
-- 当前产生的 Exp
|
||
local Val = self.CurExp + InDelta * (1 + Temp)
|
||
|
||
Val = Val + self.NextAddExp;
|
||
|
||
if Val <= 0 then
|
||
return
|
||
end
|
||
|
||
local NeedExp = self:GetNeedExpByLevel(self.Level)
|
||
|
||
while Val >= NeedExp do
|
||
self.Level = self.Level + 1
|
||
Val = Val - NeedExp
|
||
|
||
if self.Level % 10 == 0 then
|
||
self.BreachInfo.NeedBreach = true
|
||
self.BreachInfo.InBreachProgress = false
|
||
UnrealNetwork.RepLazyProperty(self, "BreachInfo")
|
||
|
||
-- 此时设置 加入之后需要添加的量
|
||
self.NextAddExp = Val
|
||
Val = 0
|
||
end
|
||
if self.Level % 8 == 0 then
|
||
local PC = UGCGameSystem.GetPlayerControllerByPlayerKey(self.PlayerKey)
|
||
UnrealNetwork.CallUnrealRPC(PC, PC, "ClientRPC_TriggerGuide", 15)
|
||
end
|
||
if self.Level == 3 then
|
||
local PC = UGCGameSystem.GetPlayerControllerByPlayerKey(self.PlayerKey)
|
||
UnrealNetwork.CallUnrealRPC(PC, PC, "ClientRPC_TriggerGuide", 31)
|
||
end
|
||
NeedExp = self:GetNeedExpByLevel(self.Level)
|
||
|
||
local PlayerPawn = UGCGameSystem.GetPlayerPawnByPlayerKey(self.PlayerKey)
|
||
self:RecoverPlayerCurHP(PlayerPawn, 0, 1.0)
|
||
self:RecoverPlayerCurEnergy(PlayerPawn, 0, 1.0)
|
||
UnrealNetwork.CallUnrealRPC_Multicast(PlayerPawn, "Client_MulticastRPC_PlayEffect", GameDataManager.GetEffectInstanceId(), 35, PlayerPawn, nil, 0, EEffectSpawnLocationType.Attach)
|
||
end
|
||
|
||
ArchiveTable.Funcs[ArchiveTable.ArchiveType.EasterEggs](self, 7)
|
||
|
||
self.CurExp = Val
|
||
|
||
EventSystem:SendEvent(EventType.ServerOnLevelAndExpChanged, self.PlayerKey, self.Level, self.CurExp, self:GetNeedExpByLevel(self.Level))
|
||
end
|
||
|
||
-- S, 杀敌后根据杀敌威力值增加威力值
|
||
function BP_PlayerState:GrowthKillAttack()
|
||
local Temp = 0
|
||
for i, v in pairs(self.Attributes) do
|
||
Temp = Temp + v.Growth_Kill_Attack
|
||
end
|
||
self.Attributes[AttributeType.Base].Base_Attack = self.Attributes[AttributeType.Base].Base_Attack + Temp
|
||
end
|
||
|
||
--- Server 重铸武器的属性
|
||
---@return bool 是否重铸成功
|
||
function BP_PlayerState:ResetWeapon(InWeaponId)
|
||
-- 移除武器的所有属性,然后再给武器添加对应这么多的属性
|
||
local FindIndex = 0
|
||
for i = 1, table.getCount(self.OwnerWeapons) do
|
||
if self.OwnerWeapons[i].WeaponId == InWeaponId then
|
||
FindIndex = i
|
||
break
|
||
end
|
||
end
|
||
|
||
if FindIndex == 0 then
|
||
UE.Log("[BP_PlayerState:ResetWeapon] 找不到对应武器:%d", InWeaponId)
|
||
return false
|
||
end
|
||
|
||
--先看一下有多少条
|
||
local PlusPropCount = #self.OwnerWeapons[FindIndex].NativeProps.Plus
|
||
self.OwnerWeapons[FindIndex].NativeProps.Plus = {}
|
||
local bSuccess = self:AddNewEntry(InWeaponId, PlusPropCount)
|
||
local PlayerCharacter = UGCGameSystem.GetPlayerPawnByPlayerKey(self.PlayerKey)
|
||
if PlayerCharacter ~= nil and PlayerCharacter.WeaponActor ~= nil then
|
||
if PlayerCharacter.WeaponActor.CurrentWeaponId == InWeaponId then
|
||
self:OnWeaponAttributeChanged(InWeaponId)
|
||
end
|
||
end
|
||
return bSuccess
|
||
end
|
||
|
||
function BP_PlayerState:OnRep_Attributes()
|
||
if GameDataManager and GameDataManager.GetLocalPlayerState() == self then
|
||
EventSystem:SendEvent(EventType.OnPlayerAttributeChanged, self.Attributes)
|
||
|
||
if self.Attributes[AttributeType.Base] and self.Attributes[AttributeType.Base].Base_Attack then
|
||
EventSystem:SendEvent(EventType.OnPlayerBaseAttackValueChanged, self.PlayerKey, self.Attributes[AttributeType.Base].Base_Attack)
|
||
end
|
||
end
|
||
end
|
||
|
||
function BP_PlayerState:OnRep_CoinPoint()
|
||
if GameDataManager and GameDataManager.GetLocalPlayerState() == self then
|
||
if EventSystem and EventType then
|
||
EventSystem:SendEvent(EventType.PlayerCoinPointChanged, self.CoinPoint.Current)
|
||
end
|
||
end
|
||
end
|
||
|
||
function BP_PlayerState:OnRep_KillPoint()
|
||
if GameDataManager and GameDataManager.GetLocalPlayerState() == self then
|
||
EventSystem:SendEvent(EventType.PlayerKillPointChanged, self.KillPoint.Current)
|
||
end
|
||
end
|
||
|
||
function BP_PlayerState:OnRep_OwnerWeapons()
|
||
-- 通知更新 武器
|
||
if EventSystem ~= nil and EventType ~= nil then
|
||
EventSystem:SendEvent(EventType.UpdateAllWeapon, self.OwnerWeapons, self.PlayerKey)
|
||
end
|
||
|
||
log_tree_dev("PlayerKey = "..tostring(self.PlayerKey) .. " ,OwnerWeapons = ", self.OwnerWeapons)
|
||
end
|
||
|
||
--这个是更新所有背包中的武器
|
||
function BP_PlayerState:OnRep_TotalWeaponCount(InOldCount)
|
||
if GameDataManager.GetLocalPlayerState() == nil then
|
||
return
|
||
end
|
||
if self.TotalWeaponCount == InOldCount then
|
||
return
|
||
end
|
||
if self.PlayerKey ~= GameDataManager.GetLocalPlayerState().PlayerKey then
|
||
return
|
||
end
|
||
|
||
--进行通知
|
||
EventSystem:SendEvent(EventType.RefreshWeapons, self.TotalWeaponCount)
|
||
end
|
||
|
||
function BP_PlayerState:OnRep_InheritItems()
|
||
if EventSystem ~= nil and EventType ~= nil then
|
||
EventSystem:SendEvent(EventType.PlayerInheritItemsChanged, self.InheritItems)
|
||
end
|
||
end
|
||
|
||
function BP_PlayerState:OnRep_BreachInfo()
|
||
UE.Log("[BP_PlayerState:OnRep_BreachInfo] NeedBreach=%s, InBreachProgress=%s", tostring(self.BreachInfo.NeedBreach), tostring(self.BreachInfo.InBreachProgress))
|
||
EventSystem:SendEvent(EventType.ToggleBreachButton, self:GetNeedShowBreachButton(), self.PlayerKey)
|
||
end
|
||
|
||
-- 获取是否能生成突破怪
|
||
function BP_PlayerState:GetCanSpawnBreachMonster()
|
||
return self.BreachInfo.NeedBreach == true and self.BreachInfo.InBreachProgress == false
|
||
end
|
||
|
||
-- 获取是否需要显示突破按钮
|
||
function BP_PlayerState:GetNeedShowBreachButton()
|
||
return self.BreachInfo.NeedBreach == true and self.BreachInfo.InBreachProgress == false
|
||
end
|
||
|
||
-- Server 应用等级改变
|
||
function BP_PlayerState:OnChangedLevel()
|
||
-- 依次添加
|
||
local IsZero = self.Level % 10 == 0
|
||
local BreachLevel = 0
|
||
if IsZero then
|
||
BreachLevel = self.Level / 10
|
||
end
|
||
|
||
self.Attributes[AttributeType.Base].Base_MaxHP = self.Attributes[AttributeType.Base].Base_MaxHP + LevelRewards.EachLevel.Health
|
||
self.Attributes[AttributeType.Base].Base_Attack = self.Attributes[AttributeType.Base].Base_Attack + LevelRewards.EachLevel.Attack
|
||
self.Attributes[AttributeType.Base].Base_Defence = self.Attributes[AttributeType.Base].Base_Defence + LevelRewards.EachLevel.Defence
|
||
|
||
if BreachLevel <= 0 then
|
||
return
|
||
end
|
||
-- Apply Attributes
|
||
-- TODO 阉割版
|
||
--self.Attributes[AttributeType.Base].Base_MaxHP = self.Attributes[AttributeType.Base].Base_MaxHP + Tables.BreachRewards[BreachLevel].Health
|
||
--self.Attributes[AttributeType.Base].Base_Attack = self.Attributes[AttributeType.Base].Base_Attack + Tables.BreachRewards[BreachLevel].Attack
|
||
--self.Attributes[AttributeType.Base].Eco_CoinPoint = self.Attributes[AttributeType.Base].Eco_CoinPoint + Tables.BreachRewards[BreachLevel].Bonus_Gold
|
||
--self.Attributes[AttributeType.Base].Base_AttackSpeed = self.Attributes[AttributeType.Base].Base_AttackSpeed + Tables.BreachRewards[BreachLevel].Attack_Speed
|
||
--self.Attributes[AttributeType.Base].Adv_FireAttack = self.Attributes[AttributeType.Base].Adv_FireAttack + Tables.BreachRewards[BreachLevel].Attack_Damage
|
||
|
||
-- -- 应用提升等级奖励
|
||
local Func = function(InLevel, InVal)
|
||
if InLevel <= 1 then
|
||
return 0
|
||
end
|
||
return LevelRewards.Rewards[InLevel - 1][InVal]
|
||
end
|
||
self.Attributes[AttributeType.Base].Base_MaxHP = self.Attributes[AttributeType.Base].Base_MaxHP + LevelRewards.Rewards[BreachLevel].Health - Func(BreachLevel, 'Health')
|
||
self.Attributes[AttributeType.Base].Base_Attack = self.Attributes[AttributeType.Base].Base_Attack + LevelRewards.Rewards[BreachLevel].Attack - Func(BreachLevel, 'Attack')
|
||
self.Attributes[AttributeType.Base].Base_AttackSpeed = self.Attributes[AttributeType.Base].Base_AttackSpeed + LevelRewards.Rewards[BreachLevel].AttackSpeed - Func(BreachLevel, 'AttackSpeed')
|
||
|
||
self.Attributes[AttributeType.Base].Growth_Kill_Attack = self.Attributes[AttributeType.Base].Growth_Kill_Attack + 1
|
||
|
||
self:ApplyAttributes()
|
||
end
|
||
|
||
--
|
||
function BP_PlayerState:GetNeedExpByLevel(InLevel)
|
||
return math.ceil((100 + 113.103448 * (InLevel - 1)) / (InLevel <= 10 and 2 or 1))
|
||
end
|
||
|
||
--
|
||
function BP_PlayerState:OnRep_AttackRange()
|
||
-- 通知更新
|
||
if EventSystem ~= nil and EventType ~= nil then
|
||
EventSystem:SendEvent(EventType.AttackRangeChanged, self.AttackRange)
|
||
end
|
||
end
|
||
|
||
--创建一个新的武器并添加到列表中
|
||
function BP_PlayerState:AddWeapon(InId)
|
||
UE.Log("[BP_PlayerState:AddWeapon] 开始添加武器,Id = %d", InId)
|
||
if not self:HasAuthority() then
|
||
return
|
||
end
|
||
-- 判断是否有对应武器
|
||
if self:FindWeaponExist(InId) then
|
||
UE.Log("[BP_PlayerState:AddWeapon] 能找到对应武器 Id: %d", InId)
|
||
-- 提示添加词条
|
||
self:AddNewEntry(InId, 2)
|
||
else
|
||
UE.Log("[BP_PlayerState:AddWeapon] 找不到对应武器,需要重新添加")
|
||
self:AddNewWeaponInternal(InId)
|
||
end
|
||
|
||
--找到对应的,
|
||
local PlayerCharacter = UGCGameSystem.GetPlayerPawnByPlayerKey(self.PlayerKey)
|
||
if PlayerCharacter ~= nil and PlayerCharacter.WeaponActor ~= nil then
|
||
PlayerCharacter.WeaponActor:SetCurrentWeapon(InId)
|
||
end
|
||
-- 阉割版
|
||
--ArchiveTable.Funcs[ArchiveTable.ArchiveType.EasterEggs](self, 9)
|
||
-- 服务端
|
||
UE.Log("[BP_PlayerState:AddWeapon] 当前的Id = %d", InId)
|
||
self:OnWeaponAttributeChanged(InId)
|
||
end
|
||
|
||
-- 移除武器但是不移除配件
|
||
function BP_PlayerState:RemoveWeapon(InWeaponId)
|
||
if self:FindWeaponById(InWeaponId) == nil then
|
||
UE.Log("[BP_PlayerState:RemoveWeapon] 没有当前武器:%d,请检查", InWeaponId)
|
||
return
|
||
end
|
||
-- 将武器身上的所有配件都移掉,再删除武器
|
||
local bSuccess = self:RemoveAllWeaponFittings(InWeaponId)
|
||
if bSuccess then
|
||
-- 从背包中删除武器
|
||
local Index = self:GetWeaponIndex(InWeaponId)
|
||
table.remove(self.OwnerWeapons, Index)
|
||
else
|
||
UE.Log("[BP_PlayerState:RemoveWeapon] 移除配件失败,请检查原因")
|
||
end
|
||
end
|
||
|
||
--这里面保存着小手枪
|
||
function BP_PlayerState:AddNewWeaponInternal(InWeaponId)
|
||
-- 判断类型
|
||
local WeaponType = GameDataManager.GetWeaponType(InWeaponId)
|
||
if WeaponType == nil then
|
||
UE.Log("[BP_PlayerState:AddNewWeaponInternal] WeaponData is nil")
|
||
return
|
||
end
|
||
|
||
local ItemData = {
|
||
WeaponId = InWeaponId,
|
||
Type = WeaponType,
|
||
|
||
-- 这个是固有属性
|
||
NativeProps = {
|
||
-- 这个是武器默认属性
|
||
Common = 0,
|
||
-- 开始拥有的高级属性
|
||
Plus = {
|
||
},
|
||
},
|
||
--这条是后面添加的词条属性
|
||
Properties = { },
|
||
--配件,存放的是Id 的数组
|
||
Fittings = { },
|
||
|
||
--- 武器的配件等级:
|
||
--- 一旦有一个格子没有配件,那就 == 0
|
||
--- 有[五个初级,五个中级)的时候就是初级 == 1
|
||
--- 有[五个中级,五个高级)的时候就是中级 == 2
|
||
--- 有[五个高级,五个超级)的时候就是高级 == 3
|
||
--- 有[五个超级]的时候就是超级 == 4
|
||
FittingLevel = 0,
|
||
}
|
||
local MainIndex, Val
|
||
if WeaponType == EWeaponClassType.WT_Pistol then
|
||
else
|
||
MainIndex, Val = RandomWeaponProperty(self)
|
||
local Pro = {MainType = MainIndex, Value = Val }
|
||
table.insert(ItemData.NativeProps.Plus, Pro)
|
||
end
|
||
|
||
self:RemovePistol()
|
||
table.insert(self.OwnerWeapons, ItemData)
|
||
|
||
-- 更新背包中武器数量
|
||
if self.OwnerWeapons[1].Type ~= EWeaponClassType.WT_Pistol then
|
||
self.TotalWeaponCount = table.getCount(self.OwnerWeapons)
|
||
end
|
||
end
|
||
|
||
--移除小手枪
|
||
function BP_PlayerState:RemovePistol()
|
||
local RemoveIndex = 0
|
||
for i = 1, #self.OwnerWeapons do
|
||
if self.OwnerWeapons[i].Type == EWeaponClassType.WT_Pistol then
|
||
RemoveIndex = i
|
||
break
|
||
end
|
||
end
|
||
-- 当不是小手枪的时候,那就移除
|
||
if RemoveIndex ~= 0 then
|
||
UE.Log("[BP_PlayerState:RemovePistol] 移除了小手枪")
|
||
table.remove(self.OwnerWeapons, RemoveIndex)
|
||
end
|
||
end
|
||
|
||
function BP_PlayerState:FindWeaponExist(InWeaponId)
|
||
for i = 1, #self.OwnerWeapons do
|
||
local Weapon = self.OwnerWeapons[i]
|
||
if Weapon.WeaponId == InWeaponId then
|
||
return true
|
||
end
|
||
end
|
||
return false
|
||
end
|
||
|
||
function BP_PlayerState:FindWeaponById(InWeaponId)
|
||
for i = 1, #self.OwnerWeapons do
|
||
if self.OwnerWeapons[i].WeaponId == InWeaponId then
|
||
return self.OwnerWeapons[i]
|
||
end
|
||
end
|
||
return nil
|
||
end
|
||
|
||
function BP_PlayerState:GetWeaponIndex(InWeaponId)
|
||
for i = 1, #self.OwnerWeapons do
|
||
if self.OwnerWeapons[i].WeaponId == InWeaponId then
|
||
return i
|
||
end
|
||
end
|
||
return -1
|
||
end
|
||
|
||
function BP_PlayerState:AddNewEntry(InWeaponId, InCount)
|
||
-- 如果是已经添加过了的,那就添加词条,如果是小手枪,那就不添加,返回
|
||
local WeaponType = GameDataManager.GetWeaponType(InWeaponId)
|
||
if WeaponType == nil or WeaponType == EWeaponClassType.WT_Pistol then
|
||
UE.Log("[BP_PlayerState:AddNewEntry] Data is nil")
|
||
return false
|
||
end
|
||
|
||
UE.Log("[BP_PlayerState:AddNewEntry] 开始给 %d 添加 %d 条词条", InWeaponId, InCount)
|
||
for _ = 1, InCount do
|
||
local MainIndex, Val = RandomWeaponProperty(self)
|
||
--在 Properties 中添加
|
||
local ItemData = {
|
||
MainType = MainIndex,
|
||
Value = Val
|
||
}
|
||
--输出一下添加的属性
|
||
UE.Log("[BP_PlayerState:AddNewEntry] 添加的属性为:%s, 值为:%s", Tables.WeaponPropertyConfig[ItemData.MainType].PropName, tostring(Val))
|
||
table.insert(self:FindWeaponById(InWeaponId).NativeProps.Plus, ItemData)
|
||
end
|
||
return true
|
||
end
|
||
|
||
-- 添加到对应武器上配件
|
||
function BP_PlayerState:AddWeaponFittingItem(InWeaponId, InItemId)
|
||
UE.Log("[BP_PlayerState:AddWeaponFittingItem] 开始添加新的配件 %d", InItemId)
|
||
if GetItemGrantTypeById(InItemId) ~= EDropItemSet.WeaponParts then
|
||
return false
|
||
end
|
||
|
||
local WeaponInfo = GameDataManager.GetWeaponConstructDataByID(InWeaponId)
|
||
if WeaponInfo == nil then
|
||
UE.Log("[BP_PlayerState:AddWeaponFittingItem] WeaponData is nil")
|
||
return false
|
||
end
|
||
local WeaponType = WeaponInfo.WeaponType
|
||
|
||
UE.Log("[BP_PlayerState:AddWeaponFittingItem] 找到武器后开始添加")
|
||
|
||
--查看是否有其他的
|
||
if self:FindTargetFittingItemExist(InWeaponId, InItemId) then
|
||
--这个是必须成功的
|
||
UE.Log("[BP_PlayerState:AddWeaponFittingItem] 开始移除原先的配件")
|
||
self:RemoveFittingItemByItemType(InWeaponId, GetItemTypeByItemId(InItemId))
|
||
end
|
||
|
||
self:AddFittingItemInternal(InWeaponId, InItemId)
|
||
|
||
-- 添加完成之后需要检查一些当前数量够不够,对于五个初级,五个中级
|
||
self:CheckFittingLevel(InWeaponId)
|
||
print(string.format("[BP_PlayerState:AddWeaponFittingItem] Weapon Type = %d", WeaponType))
|
||
self:OnWeaponAttributeChanged(InWeaponId)
|
||
end
|
||
|
||
--找到 Target 武器类型
|
||
function BP_PlayerState:FindTargetFittingItemExist(InWeaponId, InFittingItemId)
|
||
UE.Log("[BP_PlayerState:FindTargetFittingItemExist] 开始寻找对应类型的配件")
|
||
|
||
local WeaponInfo = self:FindWeaponById(InWeaponId)
|
||
if WeaponInfo == nil then
|
||
return false
|
||
end
|
||
local ItemType = GetItemTypeByItemId(InFittingItemId)
|
||
--查找对应配件
|
||
for i = 1, #WeaponInfo.Fittings do
|
||
local FittingItem = WeaponInfo.Fittings[i]
|
||
if ItemType == GetItemTypeByItemId(FittingItem) then
|
||
--说明有,进行移除操作
|
||
return true
|
||
end
|
||
end
|
||
return false
|
||
end
|
||
|
||
function BP_PlayerState:RemoveAllWeaponFittings(InWeaponId)
|
||
local Weapon = self:FindWeaponById(InWeaponId)
|
||
if Weapon == nil then
|
||
UE.Log("[BP_PlayerState:RemoveAllWeaponFittings] 没有当前武器: %d,请检查一下", InWeaponId)
|
||
return false
|
||
end
|
||
|
||
local Count = table.getCount(Weapon.Fittings)
|
||
for i = 1, Count do
|
||
local FittingId = Weapon.Fittings[i]
|
||
self:RemoveFittingItemByItemType(InWeaponId, GetItemTypeByItemId(FittingId))
|
||
end
|
||
return true
|
||
end
|
||
|
||
-- 通过武器配件类型移除武器配件
|
||
function BP_PlayerState:RemoveFittingItemByItemType(InWeaponId, InItemType)
|
||
UE.Log("[BP_PlayerState:RemoveFittingItemByItemType] 开始通过物品Type: %d 在 %d 武器中进行移除", InItemType, InWeaponId)
|
||
local RemovePos = 0
|
||
local RemoveItemId = 0
|
||
for i = 1, #self:FindWeaponById(InWeaponId).Fittings do
|
||
local FittingItem = self:FindWeaponById(InWeaponId).Fittings[i] -- 这里面只存Id,Count == 1
|
||
--这说明找到了
|
||
if GetItemTypeByItemId(FittingItem) == InItemType then
|
||
UE.Log("[BP_PlayerState:RemoveFittingItemByItemType] 找到对应选项")
|
||
RemovePos = i
|
||
RemoveItemId = FittingItem
|
||
end
|
||
end
|
||
|
||
if RemovePos == 0 then
|
||
UE.Log("[BP_PlayerState:RemoveFittingItemByItemType] 没有找到要移除的配件")
|
||
end
|
||
|
||
--添加到背包中
|
||
local PlayerController = UGCGameSystem.GetPlayerControllerByPlayerKey(self.PlayerKey)
|
||
local RemoveCount = PlayerController:UpdateItemMap(RemoveItemId, 1)
|
||
if RemoveCount == 1 then
|
||
-- 说明添加成功
|
||
UE.Log('[BP_PlayerState:RemoveFittingItemByItemType] 添加成功,开始移除')
|
||
table.remove(self:FindWeaponById(InWeaponId).Fittings, RemovePos)
|
||
else
|
||
UE.Log('[BP_PlayerState:RemoveFittingItemByItemType] 无法添加成功,请检查原因')
|
||
end
|
||
end
|
||
|
||
function BP_PlayerState:GetWeaponByFittingItemId(InFittingItemId)
|
||
local WeaponType = GetItemWeaponTypeByItemId(InFittingItemId)
|
||
for i = 1, #self.OwnerWeapons do
|
||
local Weapon = self.OwnerWeapons[i]
|
||
if Weapon.Type == WeaponType then
|
||
return Weapon
|
||
end
|
||
end
|
||
return nil
|
||
end
|
||
|
||
-- 所有武器上是否有对应Item
|
||
function BP_PlayerState:IsItemInWeapon(InFittingItemId)
|
||
for i = 1, #self.OwnerWeapons do
|
||
for j = 1, #self.OwnerWeapons[i].Fittings do
|
||
if InFittingItemId == self.OwnerWeapons[i].Fittings[j] then
|
||
return true
|
||
end
|
||
end
|
||
end
|
||
|
||
return false
|
||
end
|
||
|
||
-- 查找当前武器上是否有对应配件
|
||
function BP_PlayerState:IsItemInWeapon(InWeaponId, InFittingItemId)
|
||
local Weapon = nil
|
||
for i = 1, #self.OwnerWeapons do
|
||
if self.OwnerWeapons[i].WeaponId == InWeaponId then
|
||
Weapon = self.OwnerWeapons[i]
|
||
break
|
||
end
|
||
end
|
||
|
||
if Weapon ~= nil then
|
||
for i = 1, #Weapon.Fittings do
|
||
if Weapon.Fittings[i] == InFittingItemId then
|
||
return true
|
||
end
|
||
end
|
||
end
|
||
return false
|
||
end
|
||
|
||
-- 当前武器上是否有对应配件
|
||
function BP_PlayerState:IsCurrentWeaponHasItem(InFittingItemId)
|
||
local PlayerPawn = UGCGameSystem.GetPlayerPawnByPlayerKey(self.PlayerKey)
|
||
if PlayerPawn.WeaponActor ~= nil and UE.IsValid(PlayerPawn.WeaponActor) then
|
||
return self:IsItemInWeapon(PlayerPawn.WeaponActor.CurrentWeaponId, InFittingItemId)
|
||
end
|
||
return false
|
||
end
|
||
|
||
--实施具体的添加武器配件操作
|
||
function BP_PlayerState:AddFittingItemInternal(InWeaponId, InFittingItemId)
|
||
UE.Log("[BP_WeaponPawnBase:AddFittingItemInternal] 添加配件")
|
||
|
||
local PlayerController = UGCGameSystem.GetPlayerControllerByPlayerKey(self.PlayerKey)
|
||
local RemoveCount = PlayerController:UpdateItemMap(InFittingItemId, -1)
|
||
if RemoveCount == -1 then
|
||
local Weapon = self:FindWeaponById(InWeaponId)
|
||
UE.Log("[BP_WeaponPawnBase:AddFittingItemInternal] Weapon Id = %d", InWeaponId)
|
||
if Weapon == nil then
|
||
UE.Log("[BP_WeaponPawnBase:AddFittingItemInternal] 找不到 Weapon")
|
||
end
|
||
table.insert(Weapon.Fittings, InFittingItemId)
|
||
else
|
||
UE.Log("[BP_WeaponPawnBase:AddFittingItemInternal] 无法从背包中移除,请检查原因")
|
||
end
|
||
end
|
||
|
||
function BP_PlayerState:FindWeaponByWeaponType(InWeaponType)
|
||
for i = 1, #self.OwnerWeapons do
|
||
if self.OwnerWeapons[i].Type == InWeaponType then
|
||
return self.OwnerWeapons[i]
|
||
end
|
||
end
|
||
return nil
|
||
end
|
||
|
||
-- 从背包中移除
|
||
function BP_PlayerState:RemoveWeaponFittingItem(InFittingItemId)
|
||
self:RemoveFittingItemByItemType(self:GetWeaponByFittingItemId(InFittingItemId).WeaponId, GetItemTypeByItemId(InFittingItemId))
|
||
self:OnWeaponAttributeChanged(self:GetWeaponByFittingItemId(InFittingItemId).WeaponId)
|
||
end
|
||
|
||
-- 检查并判断当前的level,然后跟之前的level进行比较,然后增加或者删除高级属性词条
|
||
function BP_PlayerState:CheckFittingLevel(InWeaponId)
|
||
local FittingList = self:FindWeaponById(InWeaponId).Fittings
|
||
local OldFittingLevel = self:FindWeaponById(InWeaponId).FittingLevel
|
||
-- 找到 WeaponType
|
||
local ThisWeaponType = GameDataManager.GetWeaponType(InWeaponId)
|
||
if ThisWeaponType == nil then
|
||
UE.Log("[BP_PlayerState:CheckFittingLevel] Data is nil")
|
||
return
|
||
end
|
||
|
||
local NewFittingLevel
|
||
--在这里刷新一下
|
||
if #FittingList ~= 5 then
|
||
NewFittingLevel = 0
|
||
else
|
||
local Lowest = 10
|
||
local bIsSelfWeaponFitting = true
|
||
for i = 1, #FittingList do
|
||
local Item = FittingList[i]
|
||
-- 找到最低的
|
||
local Quality = GetItemQualityLevel(Item)
|
||
local WeaponType = GetItemWeaponTypeByItemId(Item)
|
||
if bIsSelfWeaponFitting and WeaponType ~= ThisWeaponType then
|
||
bIsSelfWeaponFitting = false
|
||
end
|
||
if Quality < Lowest then
|
||
Lowest = Quality
|
||
end
|
||
end
|
||
if bIsSelfWeaponFitting then
|
||
-- 说明之前都是对的,此时添加新的词条
|
||
NewFittingLevel = Lowest + 1
|
||
else
|
||
NewFittingLevel = 0
|
||
end
|
||
end
|
||
|
||
self:FindWeaponById(InWeaponId).FittingLevel = NewFittingLevel
|
||
-- 需要更新的就是 New - Old
|
||
self:UpdateFittingLevel(InWeaponId, NewFittingLevel - OldFittingLevel, NewFittingLevel)
|
||
end
|
||
|
||
function BP_PlayerState:UpdateFittingLevel(InWeaponId, InCount, InNowLevel)
|
||
UE.Log("[BP_PlayerState:UpdateFittingLevel] 要添加的武器 Id:%d, 数量:%d", InWeaponId, InCount)
|
||
if InCount == 0 then
|
||
UE.Log("[BP_PlayerState:UpdateFittingLevel] 添加物品并不能导致变化")
|
||
return
|
||
end
|
||
local Props = self:FindWeaponById(InWeaponId).Properties
|
||
if InCount < 0 then
|
||
for _ = 1, -InCount do
|
||
table.remove(self:FindWeaponById(InWeaponId).Properties, #Props)
|
||
end
|
||
else
|
||
for _ = 1, InCount do
|
||
local MainIndex, Val = RandomWeaponProperty(self)
|
||
local ItemData = {
|
||
MainType = MainIndex,
|
||
Value = Val
|
||
}
|
||
table.insert(self:FindWeaponById(InWeaponId).Properties, ItemData)
|
||
end
|
||
end
|
||
end
|
||
|
||
function BP_PlayerState:GetWeaponCount()
|
||
return #self.OwnerWeapons
|
||
end
|
||
|
||
-- SC
|
||
function BP_PlayerState:GetWeapons()
|
||
return self.OwnerWeapons
|
||
end
|
||
|
||
function BP_PlayerState:SetGameEndArchiveData(InData)
|
||
self.GameEndSavedArchiveData = InData;
|
||
end
|
||
|
||
function BP_PlayerState:AddAttribute(InType, InValue, IsChinese)
|
||
local Val = InType
|
||
if IsChinese then
|
||
Val = GlobalConfigs.AttributeNameTable[InType]
|
||
end
|
||
self.Attributes[AttributeType.Base][Val] = self.Attributes[AttributeType.Base][Val] + InValue
|
||
self:ApplyAttributes()
|
||
end
|
||
|
||
function BP_PlayerState:AddWeaponAttribute(InType, InValue)
|
||
|
||
end
|
||
|
||
function BP_PlayerState:FindPistolExist()
|
||
for i = 1, #self.OwnerWeapons do
|
||
if self.OwnerWeapons[i].Type == EWeaponClassType.WT_Pistol then
|
||
return true
|
||
end
|
||
end
|
||
return false
|
||
end
|
||
|
||
function BP_PlayerState:GetWeaponFittingsById(InWeaponId)
|
||
local Weapon = self:FindWeaponById(InWeaponId)
|
||
if Weapon == nil then
|
||
UE.Log("[BP_PlayerState:GetWeaponFittingsById] 无法找到 %d 的武器", InWeaponId)
|
||
else
|
||
return Weapon.Fittings
|
||
end
|
||
end
|
||
|
||
--当开火的时候
|
||
function BP_PlayerState:OnShot()
|
||
local Temp1, Temp2 = 0, 0
|
||
for i, v in pairs(self.Attributes) do
|
||
Temp1 = Temp1 + v.Growth_Fire_MaxHP
|
||
Temp2 = Temp2 + v.Growth_Fire_Attack
|
||
end
|
||
self.Attributes[AttributeType.Base].Base_MaxHP = self.Attributes[AttributeType.Base].Base_MaxHP + Temp1
|
||
self.Attributes[AttributeType.Base].Base_Attack = self.Attributes[AttributeType.Base].Base_Attack + Temp2
|
||
|
||
-- 造成伤害提升1点防御穿透,最高75点
|
||
if self:IsCurrentWeaponHasItem(13440) then
|
||
-- 防御穿透
|
||
if self.Attributes[AttributeType.WeaponSpecial].Adv_DefencePenetration < 75 then
|
||
self.Attributes[AttributeType.WeaponSpecial].Adv_DefencePenetration = self.Attributes[AttributeType.WeaponSpecial].Adv_DefencePenetration + 1
|
||
end
|
||
else
|
||
self.Attributes[AttributeType.WeaponSpecial].Adv_DefencePenetration = 0
|
||
end
|
||
|
||
-- 射击有5%的概率获得5000金币,如成功获得金币则进入10秒冷却期
|
||
if self:IsCurrentWeaponHasItem(14440) then
|
||
local TheId = 14440
|
||
local Rate = DropItemMap.SpecialFittingProperties[TheId][1].Probability / 100
|
||
local Cooldown = DropItemMap.SpecialFittingProperties[TheId][1].CoolDown
|
||
local Func = DropItemMap.SpecialFittingProperties[TheId][1].Func
|
||
self:RateBenefit(TheId, Rate, Cooldown, Func)
|
||
end
|
||
|
||
-- 射击有5%的概率获得150点杀敌点,如成功获得杀敌点则进入10秒冷却期
|
||
if self:IsCurrentWeaponHasItem(14140) then
|
||
local TheId = 14140
|
||
local Rate = DropItemMap.SpecialFittingProperties[TheId][1].Probability / 100
|
||
local Cooldown = DropItemMap.SpecialFittingProperties[TheId][1].CoolDown
|
||
local Func = DropItemMap.SpecialFittingProperties[TheId][1].Func
|
||
self:RateBenefit(TheId, Rate, Cooldown, Func)
|
||
end
|
||
|
||
-- 每1%的暴击伤害%加成会提高3%的射击伤害%
|
||
if self:IsCurrentWeaponHasItem(14540) then
|
||
local Attack = 0
|
||
for i, v in pairs(self.Attributes) do
|
||
Attack = Attack + v.Bonus_CriticalAttack
|
||
end
|
||
self.Attributes[AttributeType.WeaponSpecial].Adv_FireAttack = self.Attributes[AttributeType.WeaponSpecial].Adv_FireAttack + Attack * 3
|
||
else
|
||
self.Attributes[AttributeType.WeaponSpecial].Adv_FireAttack = 0
|
||
end
|
||
|
||
-- 射击会造成5%威力值的射击伤害%
|
||
if self:IsCurrentWeaponHasItem(14340) then
|
||
-- 获取威力值
|
||
local Attack = 0
|
||
for _, v in pairs(self.Attributes) do
|
||
Attack = Attack + v.Base_Attack
|
||
end
|
||
self.Attributes[AttributeType.WeaponSpecial].Adv_FireAttack = Attack * 0.05 + self.Attributes[AttributeType.WeaponSpecial].Adv_FireAttack
|
||
else
|
||
self.Attributes[AttributeType.WeaponSpecial].Adv_FireAttack = 0
|
||
end
|
||
|
||
-- 射击有10%的概率进入极速状态,该状态下射速提升100%,持续5s
|
||
if self:IsCurrentWeaponHasItem(11240) then
|
||
local TheId = 11240
|
||
local Rate = DropItemMap.SpecialFittingProperties[TheId][1].Probability / 100
|
||
local Cooldown = DropItemMap.SpecialFittingProperties[TheId][1].CoolDown
|
||
self:QuickSpeedState(TheId, Rate, Cooldown)
|
||
end
|
||
end
|
||
|
||
function BP_PlayerState:QuickSpeedState(InId, Percent, CoolDown)
|
||
if self.SpecialThings[InId] == nil then
|
||
self.SpecialThings[InId] = {}
|
||
local CurrentRealTime = KismetSystemLibrary.GetGameTimeInSeconds(self)
|
||
self.SpecialThings[InId].ServerTime = CurrentRealTime
|
||
self.SpecialThings[InId].LimitServerTime = CurrentRealTime
|
||
end
|
||
|
||
if self.SpecialThings[InId].ServerTime < self.SpecialThings[InId].LimitServerTime then
|
||
return
|
||
end
|
||
|
||
local RandomPercent = math.random()
|
||
if RandomPercent < Percent then
|
||
-- 说明成功了
|
||
self.Attributes[AttributeType.WeaponSpecial].Base_AttackSpeed = 1
|
||
EventSystem.SetTimer(self, function()
|
||
self.Attributes[AttributeType.WeaponSpecial].Base_AttackSpeed = 0
|
||
end, CoolDown)
|
||
end
|
||
end
|
||
|
||
function BP_PlayerState:RateBenefit(InId, Percent, CoolDown, InFunc)
|
||
local ServerTime = KismetSystemLibrary.GetGameTimeInSeconds(self)
|
||
if self.SpecialThings[InId] == nil then
|
||
self.SpecialThings[InId] = {}
|
||
self.SpecialThings[InId].ServerTime = ServerTime
|
||
self.SpecialThings[InId].LimitServerTime = ServerTime
|
||
end
|
||
|
||
if self.SpecialThings[InId].ServerTime < self.SpecialThings[InId].LimitServerTime then
|
||
return
|
||
end
|
||
|
||
local RandomPercent = math.random()
|
||
if RandomPercent < Percent then
|
||
-- 说明成功了
|
||
InFunc(self)
|
||
self.SpecialThings[InId].LimitServerTime = ServerTime + CoolDown
|
||
end
|
||
|
||
self.SpecialThings[InId].ServerTime = ServerTime
|
||
end
|
||
|
||
--获取练功房多加的怪物数量
|
||
function BP_PlayerState:GetMonsterSpawnAdditionCount()
|
||
local Temp = 0
|
||
for i, v in pairs(self.Attributes) do
|
||
Temp = Temp + v.Eco_HangupRoomMonsterNum
|
||
end
|
||
return Temp
|
||
end
|
||
|
||
-- 获得练功房刷怪效率
|
||
function BP_PlayerState:GetMonsterRefreshEfficiency()
|
||
local Temp = 0
|
||
for i, v in pairs(self.Attributes) do
|
||
Temp = Temp + v.Eco_HangupRoomRefreshRate
|
||
end
|
||
return Temp
|
||
end
|
||
|
||
-- 获取所有武器上的装备
|
||
function BP_PlayerState:GetAllEquipment()
|
||
local OutData = {}
|
||
for i, v in ipairs(self.OwnerWeapons) do
|
||
for c, d in pairs(v.Fittings) do
|
||
table.insert(OutData, d)
|
||
end
|
||
end
|
||
return OutData
|
||
end
|
||
|
||
return BP_PlayerState; |