681 lines
23 KiB
Lua
681 lines
23 KiB
Lua
|
---@class BP_MonsterBase_C:STExtraSimpleCharacter
|
|||
|
---@field ParticleSystem_Stun UParticleSystemComponent
|
|||
|
---@field MonsterAnimList UUAEMonsterAnimListComponent
|
|||
|
---@field Capsule UCapsuleComponent
|
|||
|
---@field HurtEffect UParticleSystem
|
|||
|
---@field TargetPlayerKey int64
|
|||
|
--Edit Below--
|
|||
|
local BP_MonsterBase = {
|
|||
|
ID = 0;
|
|||
|
|
|||
|
DeadExp = 0;
|
|||
|
DeadCoinPoint = 0;
|
|||
|
DeadKillPoint = 1;
|
|||
|
|
|||
|
ModifyDamageDelegation = {}; -- 修改收到伤害的委托
|
|||
|
SkillCount = 0;
|
|||
|
MonsterName = "";
|
|||
|
-- ID = 0;
|
|||
|
bIsDead = false;
|
|||
|
bIsStun = false; --是否眩晕
|
|||
|
|
|||
|
bHasInitedByLevel = false;
|
|||
|
bHasTriggeredReceiveOnDeath = false;
|
|||
|
|
|||
|
AttackValue = 0;
|
|||
|
MagicValue = 0;
|
|||
|
BossLevel = 0;
|
|||
|
PhysicalDefense = 0;
|
|||
|
MagicDefense = 0;
|
|||
|
Gold = 0;
|
|||
|
KillPoint = 0;
|
|||
|
exp = 0;
|
|||
|
|
|||
|
-- 附加攻击力
|
|||
|
AdditionalAttack = 0;
|
|||
|
-- 附加防御力
|
|||
|
AdditionalDefense = 0;
|
|||
|
--攻击力效率
|
|||
|
AttackScale = 1;
|
|||
|
--防御力效率
|
|||
|
DefenseScale = 1;
|
|||
|
-- 应用附加攻击力
|
|||
|
ApplyAdditionalAttack = 1;
|
|||
|
-- 应用附加防御力
|
|||
|
ApplyAdditionalDefense = 1;
|
|||
|
-- 回血效率
|
|||
|
BloodReturnEfficiency = 1;
|
|||
|
-- 伤害减免百分比
|
|||
|
DamageReductionPercentage = 0;
|
|||
|
-- 追踪玩家范围
|
|||
|
TrackPlayerRange = 1000;
|
|||
|
|
|||
|
bSetWeaponSkill = false;
|
|||
|
};
|
|||
|
|
|||
|
---------------------------------属性同步---------------------------------
|
|||
|
|
|||
|
function BP_MonsterBase:GetReplicatedProperties()
|
|||
|
return
|
|||
|
"TargetPlayerKey", "bIsStun"
|
|||
|
end
|
|||
|
|
|||
|
function BP_MonsterBase:OnRep_bIsStun()
|
|||
|
if self.bIsStun then
|
|||
|
self.ParticleSystem_Stun:SetVisibility(true)
|
|||
|
else
|
|||
|
self.ParticleSystem_Stun:SetVisibility(false)
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
function BP_MonsterBase:OnRep_TargetPlayerKey()
|
|||
|
print(string.format('[BP_MonsterBase:OnRep_TargetPlayerKey] 同步 PlayerKey = %d', self.TargetPlayerKey))
|
|||
|
end
|
|||
|
|
|||
|
---------------------------------初始化流程---------------------------------
|
|||
|
|
|||
|
function BP_MonsterBase:ReceiveBeginPlay()
|
|||
|
BP_MonsterBase.SuperClass.ReceiveBeginPlay(self)
|
|||
|
|
|||
|
if self:HasAuthority() then
|
|||
|
self.OnDeath:Add(BP_MonsterBase.ServerOnDeath, self)
|
|||
|
else
|
|||
|
self.OnSimpleCharacterHpChange:Add(BP_MonsterBase.ClientOnHealthChanged, self)
|
|||
|
end
|
|||
|
|
|||
|
self:ReceiveBeginPlayEx()
|
|||
|
end
|
|||
|
|
|||
|
function BP_MonsterBase:ReceiveTick(DeltaTime)
|
|||
|
BP_MonsterBase.SuperClass.ReceiveTick(self, DeltaTime);
|
|||
|
|
|||
|
self:ReceiveTickEx(DeltaTime)
|
|||
|
end
|
|||
|
|
|||
|
function BP_MonsterBase:ReceiveEndPlay()
|
|||
|
self:ReceiveOnDeath()
|
|||
|
|
|||
|
if self:HasAuthority() then
|
|||
|
self.OnDeath:Remove(BP_MonsterBase.ServerOnDeath, self)
|
|||
|
|
|||
|
self.bIsStun = false
|
|||
|
if self.StunTimerHandle ~= nil then
|
|||
|
EventSystem.StopTimer(self.StunTimerHandle)
|
|||
|
end
|
|||
|
else
|
|||
|
self.ParticleSystem_Stun:SetVisibility(false)
|
|||
|
end
|
|||
|
|
|||
|
self:ReceiveEndPlayEx()
|
|||
|
|
|||
|
BP_MonsterBase.SuperClass.ReceiveEndPlay(self)
|
|||
|
end
|
|||
|
|
|||
|
---额外初始化项的接口
|
|||
|
---子类中实现
|
|||
|
function BP_MonsterBase:ReceiveBeginPlayEx()
|
|||
|
end
|
|||
|
|
|||
|
---额外Tick操作接口
|
|||
|
---子类中实现
|
|||
|
function BP_MonsterBase:ReceiveTickEx(DeltaTime)
|
|||
|
end
|
|||
|
|
|||
|
---额外销毁项的接口
|
|||
|
---子类中实现
|
|||
|
function BP_MonsterBase:ReceiveEndPlayEx()
|
|||
|
end
|
|||
|
|
|||
|
---客户端血量变化回调
|
|||
|
function BP_MonsterBase:ClientOnHealthChanged(CurrentHP, MaxHP)
|
|||
|
self:ClientOnHealthChangedEx(CurrentHP, MaxHP)
|
|||
|
end
|
|||
|
|
|||
|
---客户端血量变化回调
|
|||
|
---子类中实现
|
|||
|
function BP_MonsterBase:ClientOnHealthChangedEx(CurrentHP, MaxHP)
|
|||
|
end
|
|||
|
|
|||
|
----------------------------------------死亡回调函数----------------------------------------
|
|||
|
|
|||
|
function BP_MonsterBase:ServerOnDeath(DeadMonster, KillerController, DamageCauser, KillingHitInfo, KillingHitImpulseDir, KillingHitDamageTypeID, DamageTypeClass, IsHeadShotDamage)
|
|||
|
if DeadMonster == self then
|
|||
|
local PlayerState = UGCGameSystem.GetPlayerStateByPlayerKey(KillerController.PlayerKey)
|
|||
|
PlayerState:AddExp(self:GetDeadExp())
|
|||
|
PlayerState:AddCoinPoint(self:GetDeadCoinPoint())
|
|||
|
PlayerState:AddKillPoint(self:GetDeadKillPoint())
|
|||
|
PlayerState:AddKillCount()
|
|||
|
|
|||
|
KillerController:AddSealKillCount()
|
|||
|
|
|||
|
local Rand = math.random(1, 100)
|
|||
|
local DropItemAddition = PlayerState:GetDroppingRate()
|
|||
|
if Rand < (self:GetDropRate() * (1 + DropItemAddition)) then
|
|||
|
local DropPos = VectorHelper.Sub(self:K2_GetActorLocation(), {X = 0, Y = 0, Z = self.Capsule.CapsuleHalfHeight})
|
|||
|
EventSystem:SendEvent(EventType.SpawnDropItem, DropPos, self:K2_GetActorRotation(), KillerController.PlayerKey, nil)
|
|||
|
end
|
|||
|
|
|||
|
self.bIsDead = true
|
|||
|
self.bIsStun = false
|
|||
|
if self.StunTimerHandle ~= nil then
|
|||
|
EventSystem.StopTimer(self.StunTimerHandle)
|
|||
|
end
|
|||
|
|
|||
|
self:ReceiveOnDeath()
|
|||
|
|
|||
|
self:ServerOnDeathEx(DeadMonster, KillerController, DamageCauser, KillingHitInfo, KillingHitImpulseDir, KillingHitDamageTypeID, DamageTypeClass, IsHeadShotDamage)
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
function BP_MonsterBase:ReceiveOnDeath()
|
|||
|
if self.bHasTriggeredReceiveOnDeath then
|
|||
|
return
|
|||
|
end
|
|||
|
self.bHasTriggeredReceiveOnDeath = true
|
|||
|
|
|||
|
self:ReceiveOnMonsterDeath()
|
|||
|
|
|||
|
if self:HasAuthority() then
|
|||
|
UnrealNetwork.CallUnrealRPC_Multicast(self, "ReceiveOnMonsterDeath")
|
|||
|
UnrealNetwork.CallUnrealRPC_Multicast(self, "Client_MulticastRPC_RemoveAllSkillEffect", self)
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
---当收到死亡回调后的处理项接口(服务器和客户端都会运行)
|
|||
|
---子类中实现
|
|||
|
function BP_MonsterBase:ReceiveOnMonsterDeath()
|
|||
|
end
|
|||
|
|
|||
|
---死亡回调额外处理项接口
|
|||
|
---子类中实现
|
|||
|
function BP_MonsterBase:ServerOnDeathEx(DeadMonster, KillerController, DamageCauser, KillingHitInfo, KillingHitImpulseDir, KillingHitDamageTypeID, DamageTypeClass, IsHeadShotDamage)
|
|||
|
end
|
|||
|
|
|||
|
-- 处理飘字
|
|||
|
function BP_MonsterBase:UGC_GetDamageNumberConfigIndex(Damage, IsHeadShot, InstigatorController, DamageCauser, DamageType)
|
|||
|
if not self:HasAuthority() then
|
|||
|
GameplayStatics.SpawnEmitterAttached(self.HurtEffect, self.Mesh, "spine_01", VectorHelper.VectorZero(), VectorHelper.RotZero(), VectorHelper.Scale(2.0), EAttachLocation.SnapToTarget, true)
|
|||
|
end
|
|||
|
|
|||
|
if (not InstigatorController) or (not DamageCauser:IsLocallyControlled()) then
|
|||
|
return -1
|
|||
|
end
|
|||
|
|
|||
|
UE.Log("[BP_MonsterBase:UGC_GetDamageNumberConfigIndex] 0")
|
|||
|
return 0
|
|||
|
end
|
|||
|
|
|||
|
---------------------------------初始化属性流程---------------------------------
|
|||
|
|
|||
|
function BP_MonsterBase:InitMonsterByLevel(InLevel)
|
|||
|
self.bHasInitedByLevel = false
|
|||
|
return self:UpdateMonsterLevel(self.MonsterName, InLevel)
|
|||
|
end
|
|||
|
|
|||
|
---更新怪物等级
|
|||
|
function BP_MonsterBase:UpdateMonsterLevel(MonsterName, newLevel)
|
|||
|
if self.bHasInitedByLevel then
|
|||
|
return true
|
|||
|
end
|
|||
|
self.bHasInitedByLevel = true
|
|||
|
|
|||
|
if self.HealthCheckHandle ~= nil then
|
|||
|
EventSystem.StopTimer(self.HealthCheckHandle)
|
|||
|
self.HealthCheckHandle = nil
|
|||
|
end
|
|||
|
|
|||
|
if MonsterName == self.MonsterName and self.BossLevel == newLevel then
|
|||
|
UE.Log("[BP_MonsterBase][UpdateMonsterLevel] %s: Has Inited", KismetSystemLibrary.GetObjectName(self))
|
|||
|
return true
|
|||
|
end
|
|||
|
|
|||
|
self.bSetWeaponSkill = false
|
|||
|
|
|||
|
local GameState = UGCGameSystem.GameState
|
|||
|
|
|||
|
if UE.IsValid(GameState) == false then
|
|||
|
UE.Log("[BP_MonsterBase][UpdateMonsterLevel] invalid gamestate")
|
|||
|
return false
|
|||
|
end
|
|||
|
|
|||
|
local MultiplierBoss = GameState.BossHealthMultiplier
|
|||
|
local MultiplierMonster = GameState.MonsterHealthAndAttackValueMultiplier
|
|||
|
|
|||
|
if ((type(newLevel) == "number") and MonsterParam[MonsterName]) then
|
|||
|
|
|||
|
self.BossLevel = newLevel
|
|||
|
local MonsterType = self:GetMonsterType()
|
|||
|
local HealthMax = MonsterParam[MonsterName].GradeParam[self.BossLevel].Health * MultiplierMonster["Health"]
|
|||
|
if MonsterType == EMonsterType.Boss then
|
|||
|
HealthMax = HealthMax * MultiplierBoss
|
|||
|
end
|
|||
|
UGCSimpleCharacterSystem.SetHealthMax(self, HealthMax)
|
|||
|
UGCSimpleCharacterSystem.SetHealth(self, HealthMax)
|
|||
|
|
|||
|
self.HealthCheckHandle = EventSystem.SetTimerLoop(self, function()
|
|||
|
local HealthMax = UGCSimpleCharacterSystem.GetHealthMax(self)
|
|||
|
local Health = UGCSimpleCharacterSystem.GetHealth(self)
|
|||
|
if math.isNearlyEqual(Health, HealthMax, 10000) == false then
|
|||
|
UGCSimpleCharacterSystem.SetHealth(self, HealthMax)
|
|||
|
|
|||
|
local Now_HealthMax = UGCSimpleCharacterSystem.GetHealthMax(self)
|
|||
|
local Now_Health = UGCSimpleCharacterSystem.GetHealth(self)
|
|||
|
|
|||
|
local LogStr = string.format("[BP_MonsterBase][CheckMonsterHealth] %s: Reset Health: HealthMax = %.2f, Health = %.2f; ", KismetSystemLibrary.GetObjectName(self), Now_HealthMax, Now_Health)
|
|||
|
if math.isNearlyEqual(Now_HealthMax, Now_Health, 10000) then
|
|||
|
LogStr = LogStr.." Stop Timer !"
|
|||
|
EventSystem.StopTimer(self.HealthCheckHandle)
|
|||
|
end
|
|||
|
UE.Log(LogStr)
|
|||
|
else
|
|||
|
UE.Log("[BP_MonsterBase][CheckMonsterHealth] %s: Valid Health: HealthMax = %.2f, Health = %.2f", KismetSystemLibrary.GetObjectName(self), HealthMax, Health)
|
|||
|
EventSystem.StopTimer(self.HealthCheckHandle)
|
|||
|
end
|
|||
|
end, 0.5)
|
|||
|
|
|||
|
self.AttackValue = MonsterParam[MonsterName].GradeParam[self.BossLevel].AttackValue * MultiplierMonster["Attack"]
|
|||
|
self.PhysicalDefense = MonsterParam[MonsterName].GradeParam[self.BossLevel].PhysicalDefense
|
|||
|
|
|||
|
local MaxWalkSpeed = MonsterParam[MonsterName].GradeParam[self.BossLevel].MovementSpeed
|
|||
|
UGCSimpleCharacterSystem.SetSpeedScale(self, MaxWalkSpeed / 600)
|
|||
|
|
|||
|
self.DeadCoinPoint = MonsterParam[MonsterName].GradeParam[self.BossLevel].Gold
|
|||
|
self.DeadExp = MonsterParam[MonsterName].GradeParam[self.BossLevel].exp
|
|||
|
self.DeadKillPoint = MonsterParam[MonsterName].GradeParam[self.BossLevel].KillPoint
|
|||
|
|
|||
|
self.BaseHealthMax = HealthMax
|
|||
|
self.BaseAttackValue = self.AttackValue
|
|||
|
self.BasePhysicalDefense = self.PhysicalDefense
|
|||
|
self.BaseMaxWalkSpeed = MaxWalkSpeed
|
|||
|
|
|||
|
if MonsterType ~= EMonsterType.Breach then
|
|||
|
local LifeTime = MonsterParam[MonsterName].GradeParam[self.BossLevel].LifeTime
|
|||
|
if LifeTime and LifeTime > 0 then
|
|||
|
self:SetLifeSpan(LifeTime)
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
self:UpdateMonsterLevelEx(MonsterName, newLevel)
|
|||
|
else
|
|||
|
UE.Log("[BP_MonsterBase][UpdateMonsterLevel] Failure: invalid level or monstername")
|
|||
|
return false
|
|||
|
end
|
|||
|
|
|||
|
return true
|
|||
|
end
|
|||
|
|
|||
|
---更新怪物等级其他项
|
|||
|
---子类实现
|
|||
|
function BP_MonsterBase:UpdateMonsterLevelEx(MonsterName, newLevel)
|
|||
|
end
|
|||
|
|
|||
|
function BP_MonsterBase:UpdateSkillCount()
|
|||
|
self.SkillCount = self.SkillCount + 1
|
|||
|
end
|
|||
|
|
|||
|
---怪物应用伤害
|
|||
|
function BP_MonsterBase:MonsterApplyDamage(TargetPawn, DamageValue)
|
|||
|
if self.bIsDead then return end
|
|||
|
if TargetPawn == nil then return end
|
|||
|
local juryReduction = 0
|
|||
|
local PlayerState = TargetPawn.PlayerState
|
|||
|
if PlayerState and PlayerState.InjuryReduction then
|
|||
|
juryReduction = PlayerState:InjuryReduction(self)
|
|||
|
end
|
|||
|
DamageValue = DamageValue - juryReduction
|
|||
|
if DamageValue < 0 then
|
|||
|
DamageValue = 0
|
|||
|
end
|
|||
|
print("BP_MonsterBase_Fun_" .. "MonsterApplyDamage_ " .. DamageValue)
|
|||
|
UGCGameSystem.ApplyDamage(TargetPawn, DamageValue, self:GetController(), self, EDamageType.ShootDamage)
|
|||
|
end
|
|||
|
|
|||
|
|
|||
|
---------------------------------Get&Set---------------------------------
|
|||
|
|
|||
|
-- virtual
|
|||
|
function BP_MonsterBase:GetDeadExp()
|
|||
|
return self.DeadExp
|
|||
|
end
|
|||
|
|
|||
|
function BP_MonsterBase:GetDeadCoinPoint()
|
|||
|
return self.DeadCoinPoint
|
|||
|
end
|
|||
|
|
|||
|
function BP_MonsterBase:GetDeadKillPoint()
|
|||
|
return self.DeadKillPoint
|
|||
|
end
|
|||
|
|
|||
|
function BP_MonsterBase:GetDropRate()
|
|||
|
return 10
|
|||
|
end
|
|||
|
|
|||
|
function BP_MonsterBase:GetMonsterType()
|
|||
|
return GameDataManager.GetMonsterTypeByID(self.ID)
|
|||
|
end
|
|||
|
|
|||
|
---Server
|
|||
|
function BP_MonsterBase:SetTargetPlayerKey(InPlayerKey)
|
|||
|
self.TargetPlayerKey = InPlayerKey
|
|||
|
-- UE.Log("[BP_MonsterBase][SetTargetPlayerKey] [%s]: TargetPlayerKey[%s]", KismetSystemLibrary.GetObjectName(self), tostring(self.TargetPlayerKey))
|
|||
|
end
|
|||
|
|
|||
|
---Server
|
|||
|
function BP_MonsterBase:SetIsStun(flag, Duration)
|
|||
|
if not self:IsAlive() then
|
|||
|
return
|
|||
|
end
|
|||
|
if flag then
|
|||
|
if Duration > 0 then
|
|||
|
if self.StunTimerHandle ~= nil then
|
|||
|
EventSystem.StopTimer(self.StunTimerHandle)
|
|||
|
end
|
|||
|
|
|||
|
self.StunTimerHandle = EventSystem.SetTimer(self, function()
|
|||
|
self.bIsStun = false
|
|||
|
end, Duration)
|
|||
|
else
|
|||
|
return
|
|||
|
end
|
|||
|
end
|
|||
|
self.bIsStun = flag
|
|||
|
end
|
|||
|
|
|||
|
|
|||
|
function BP_MonsterBase:GetCanDamagePlayer()
|
|||
|
return GameplayStatics.GetAllActorsOfClass(self, self:GetPawnClass(), {})
|
|||
|
end
|
|||
|
|
|||
|
---设置血量恢复效率
|
|||
|
---@field NewBloodReturnEfficiency float
|
|||
|
function BP_MonsterBase:SetBloodReturnEfficiency(NewBloodReturnEfficiency)
|
|||
|
if NewBloodReturnEfficiency < 0 then return false end
|
|||
|
self.BloodReturnEfficiency = NewBloodReturnEfficiency
|
|||
|
return true
|
|||
|
end
|
|||
|
|
|||
|
---恢复怪物的血量,自动控制在血量上限
|
|||
|
---@field TargetAddHealth float
|
|||
|
function BP_MonsterBase:AddHealth(TargetAddHealth)
|
|||
|
TargetAddHealth = self.BloodReturnEfficiency * TargetAddHealth
|
|||
|
|
|||
|
local TargetHealth = UGCSimpleCharacterSystem.GetHealth(self) + TargetAddHealth
|
|||
|
if TargetHealth > UGCSimpleCharacterSystem.GetHealthMax(self) then
|
|||
|
TargetHealth = UGCSimpleCharacterSystem.GetHealthMax(self)
|
|||
|
end
|
|||
|
UGCSimpleCharacterSystem.SetHealth(self, TargetHealth)
|
|||
|
end
|
|||
|
|
|||
|
---获取攻击力
|
|||
|
---@return float
|
|||
|
function BP_MonsterBase:GetAttack()
|
|||
|
return self.AttackScale * (self.AttackValue + (self.AdditionalAttack * self.ApplyAdditionalAttack))
|
|||
|
end
|
|||
|
|
|||
|
---获取防御力
|
|||
|
---@return float
|
|||
|
function BP_MonsterBase:GetDefense()
|
|||
|
return self.DefenseScale * (self.PhysicalDefense + (self.AdditionalDefense * self.ApplyAdditionalDefense))
|
|||
|
end
|
|||
|
|
|||
|
---设置攻击缩放
|
|||
|
---@field NewAttackScale float
|
|||
|
---@return bool
|
|||
|
function BP_MonsterBase:SetAttackScale(NewAttackScale)
|
|||
|
if NewAttackScale < 0 then return false end
|
|||
|
self.AttackScale = NewAttackScale
|
|||
|
return true
|
|||
|
end
|
|||
|
|
|||
|
---设置防御缩放
|
|||
|
---@field NewDefenseScale float
|
|||
|
---@return bool
|
|||
|
function BP_MonsterBase:SetDefenseScale(NewDefenseScale)
|
|||
|
if NewDefenseScale < 0 then return false end
|
|||
|
self.DefenseScale = NewDefenseScale
|
|||
|
return true
|
|||
|
end
|
|||
|
|
|||
|
---设置应用攻击附加
|
|||
|
---@field NewApplyAdditionalAttack bool
|
|||
|
function BP_MonsterBase:SetApplyAdditionalAttack(NewApplyAdditionalAttack)
|
|||
|
if NewApplyAdditionalAttack then
|
|||
|
self.ApplyAdditionalAttack = 1
|
|||
|
else
|
|||
|
self.ApplyAdditionalAttack = 0
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
---设置设置应用防御附加
|
|||
|
---@field NewApplyAdditionalDefense bool
|
|||
|
function BP_MonsterBase:SetApplyAdditionalDefense(NewApplyAdditionalDefense)
|
|||
|
if NewApplyAdditionalDefense then
|
|||
|
self.ApplyAdditionalDefense = 1
|
|||
|
else
|
|||
|
self.ApplyAdditionalDefense = 0
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
---添加攻击力附加
|
|||
|
function BP_MonsterBase:AddAdditionalAttack(Val)
|
|||
|
self.AdditionalAttack = Val + self.AdditionalAttack
|
|||
|
end
|
|||
|
|
|||
|
---添加防御力附加
|
|||
|
function BP_MonsterBase:AddAdditionalDefense(Val)
|
|||
|
self.AdditionalDefense = Val + self.AdditionalDefense
|
|||
|
end
|
|||
|
|
|||
|
---重置额外攻击力
|
|||
|
function BP_MonsterBase:ResetAdditionalAttack(Val)
|
|||
|
self.AdditionalAttack = Val
|
|||
|
end
|
|||
|
|
|||
|
---重置额外防御力
|
|||
|
function BP_MonsterBase:ResetAdditionalDefense(Val)
|
|||
|
self.AdditionalDefense = Val
|
|||
|
end
|
|||
|
|
|||
|
---@field CenterPosition Vector
|
|||
|
---@field radius float
|
|||
|
---@field TargetClass UClass
|
|||
|
---@return resActors table
|
|||
|
function BP_MonsterBase:GetSphereActors(CenterPosition, radius, TargetClass)
|
|||
|
local TargetActors = GameplayStatics.GetAllActorsOfClass(self, TargetClass, {})
|
|||
|
local resActors = {}
|
|||
|
for k, TempActor in pairs(TargetActors) do
|
|||
|
if VectorHelper.GetDistance(TempActor:K2_GetActorLocation(), CenterPosition) <= radius then
|
|||
|
table.insert(resActors, TempActor)
|
|||
|
end
|
|||
|
end
|
|||
|
return resActors
|
|||
|
end
|
|||
|
|
|||
|
function BP_MonsterBase:GetPawnClass()
|
|||
|
if not self.PawnClass then
|
|||
|
self.PawnClass = UE.LoadClass(BPClassPath.PlayerPawn)
|
|||
|
end
|
|||
|
return self.PawnClass
|
|||
|
end
|
|||
|
|
|||
|
function BP_MonsterBase:GetMonsterClass()
|
|||
|
if not self.MonsterClass then
|
|||
|
self.MonsterClass = UE.LoadClass(UGCGameSystem.GetUGCResourcesFullPath('Asset/Blueprint/Monster/BP_MonsterBase.BP_MonsterBase_C'))
|
|||
|
end
|
|||
|
return self.MonsterClass
|
|||
|
end
|
|||
|
|
|||
|
---------------------------------伤害处理---------------------------------
|
|||
|
|
|||
|
---伤害处理函数
|
|||
|
function BP_MonsterBase:BP_CharacterModifyDamage(DamageAmount, DamageEvent, EventInstigator, DamageCauser)
|
|||
|
local BaseDamageAmount = DamageAmount
|
|||
|
|
|||
|
DamageAmount = BP_MonsterBase.ReduceInjury(self, DamageCauser, DamageAmount)
|
|||
|
|
|||
|
if self.ModifyDamageDelegation then
|
|||
|
for k, fun in pairs(self.ModifyDamageDelegation) do
|
|||
|
DamageAmount = fun(DamageAmount, DamageEvent, EventInstigator, DamageCauser)
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
if DamageCauser.IsInTrueDamage then
|
|||
|
DamageAmount = BaseDamageAmount
|
|||
|
end
|
|||
|
|
|||
|
if DamageAmount < 0 then
|
|||
|
DamageAmount = 0
|
|||
|
end
|
|||
|
|
|||
|
DamageAmount = self:DealWeapon(DamageCauser, DamageAmount)
|
|||
|
|
|||
|
if EventInstigator then
|
|||
|
local ControlledCharacter = EventInstigator:GetPlayerCharacterSafety()
|
|||
|
ControlledCharacter:DealRealDamage(self, DamageAmount)
|
|||
|
end
|
|||
|
|
|||
|
self:CollectPlayerDamage(DamageAmount, EventInstigator.PlayerKey)
|
|||
|
|
|||
|
DamageAmount = self:BP_CharacterModifyDamageEx(DamageAmount)
|
|||
|
|
|||
|
return DamageAmount
|
|||
|
end
|
|||
|
|
|||
|
---额外伤害处理接口
|
|||
|
---子类实现
|
|||
|
function BP_MonsterBase:BP_CharacterModifyDamageEx(DamageAmount)
|
|||
|
return DamageAmount
|
|||
|
end
|
|||
|
|
|||
|
--收到伤害时触发, Server调用, 顺序在ModifyDamage之后, DamageAmout应是计算过后的伤害
|
|||
|
function BP_MonsterBase:BPReceiveDamage(DamageAmount, DamageType, EventInstigator, DamageCauser)
|
|||
|
self:BPReceiveDamageEx(DamageAmount, DamageType, EventInstigator, DamageCauser)
|
|||
|
end
|
|||
|
|
|||
|
---子类中实现
|
|||
|
function BP_MonsterBase:BPReceiveDamageEx(DamageAmount, DamageType, EventInstigator, DamageCauser)
|
|||
|
end
|
|||
|
|
|||
|
--[[
|
|||
|
|
|||
|
time: 20230312
|
|||
|
name: LanTian
|
|||
|
describe:
|
|||
|
添加一个ModifyDamageDelegation的委托table,作用于重载的伤害修改函数BP_CharacterModifyDamage,便利所有的修改委托函数后返回最终伤害值
|
|||
|
AddModifyDamageDelegation : 添加一个委托
|
|||
|
RemoveModifyDamageDelegation : 移除一个委托
|
|||
|
|
|||
|
]]--
|
|||
|
function BP_MonsterBase.ReduceInjury(Monster, Pawn, DamageAmount)
|
|||
|
local ReduceInjury = 0
|
|||
|
if UE.IsValid(Monster) and UE.IsValid(Pawn) and UE.IsValid(Pawn.PlayerState) and Monster.GetDefense and Pawn.PlayerState.DefencePenetrate then
|
|||
|
ReduceInjury = (Monster:GetDefense() - Pawn.PlayerState:DefencePenetrate()) / ((Monster:GetDefense() - Pawn.PlayerState:DefencePenetrate()) + 1000)
|
|||
|
local OldDamage = DamageAmount
|
|||
|
DamageAmount = DamageAmount * (1 - ReduceInjury) * (1 - Monster.DamageReductionPercentage)
|
|||
|
|
|||
|
if GameDataManager.GetMonsterTypeByID(Monster.ID) == EMonsterType.Boss then
|
|||
|
UE.Log("[BP_MonsterBoss:ReduceInjury] %s: OldDmg=%.2f, Result=%.2f", KismetSystemLibrary.GetObjectName(Monster), OldDamage, DamageAmount)
|
|||
|
end
|
|||
|
UE.Log("[BP_MonsterBase_ReduceInjury] %f", DamageAmount)
|
|||
|
end
|
|||
|
return DamageAmount
|
|||
|
end
|
|||
|
|
|||
|
|
|||
|
function BP_MonsterBase:DealWeapon(InDamageCauser, InDamageAmount)
|
|||
|
local WeaponType = GameDataManager.GetWeaponType(InDamageCauser.WeaponActor.CurrentWeaponId)
|
|||
|
if WeaponType == nil then
|
|||
|
UE.Log("[BP_MonsterBase:DealWeapon] Data is nil")
|
|||
|
return
|
|||
|
else
|
|||
|
if WeaponType == EWeaponClassType.WT_ShotGun then -- 霰弹枪
|
|||
|
if self.ID == 10006 and self.bIsReplica then
|
|||
|
InDamageAmount = InDamageAmount * 4
|
|||
|
UE.Log('[BP_MonsterBase:DealWeapon] 霰弹枪: 攻击分身伤害:%f ---SelfName=%s', InDamageAmount, KismetSystemLibrary.GetObjectName(self))
|
|||
|
end
|
|||
|
elseif WeaponType == EWeaponClassType.WT_MachineGun then -- 机枪
|
|||
|
--self.
|
|||
|
elseif WeaponType == EWeaponClassType.WT_SubmachineGun then -- 冲锋枪
|
|||
|
InDamageCauser.bCanBeControlledByMonsters = true
|
|||
|
if GameDataManager.GetMonsterTypeByID(self.ID) == EMonsterType.Boss then
|
|||
|
UE.Log('[BP_MonsterBase:DealWeapon] 冲锋枪: 免疫控制 ---SelfName=%s', KismetSystemLibrary.GetObjectName(self))
|
|||
|
end
|
|||
|
elseif WeaponType == EWeaponClassType.WT_ShooterRifle then -- 射手步枪
|
|||
|
if GameDataManager.GetMonsterTypeByID(self.ID) == EMonsterType.Boss then
|
|||
|
if not self.bSetWeaponSkill then
|
|||
|
local SpeedScale = UGCSimpleCharacterSystem.GetSpeedScale(self)
|
|||
|
UGCSimpleCharacterSystem.SetSpeedScale(self, SpeedScale * 0.3)
|
|||
|
self.bSetWeaponSkill = true
|
|||
|
UE.Log('[BP_MonsterBase:DealWeapon] 射手步枪: 减速 ---SelfName=%s', KismetSystemLibrary.GetObjectName(self))
|
|||
|
end
|
|||
|
end
|
|||
|
elseif WeaponType == EWeaponClassType.WT_AssaultRifle then -- 突击步枪
|
|||
|
if GameDataManager.GetMonsterTypeByID(self.ID) == EMonsterType.Boss then
|
|||
|
self:SetBloodReturnEfficiency(0)
|
|||
|
UE.Log('[BP_MonsterBase:DealWeapon] 突击步枪: 抑制回复 ---SelfName=%s', KismetSystemLibrary.GetObjectName(self))
|
|||
|
end
|
|||
|
elseif WeaponType == EWeaponClassType.WT_Sniper then -- 狙击枪
|
|||
|
if GameDataManager.GetMonsterTypeByID(self.ID) == EMonsterType.Boss then
|
|||
|
self:SetApplyAdditionalDefense(false)
|
|||
|
UE.Log('[BP_MonsterBase:DealWeapon] 狙击枪: 无视防御 ---SelfName=%s', KismetSystemLibrary.GetObjectName(self))
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
return InDamageAmount
|
|||
|
end
|
|||
|
|
|||
|
function BP_MonsterBase:CollectPlayerDamage(DamageAmount, PlayerKey)
|
|||
|
if PlayerKey == nil then
|
|||
|
UE.Log("BP_MonsterBase_Fun_" .. "CollectPlayerDamage" .. "PlayerKey is nil")
|
|||
|
return
|
|||
|
end
|
|||
|
if self:GetMonsterType() == EMonsterType.Boss then
|
|||
|
if DamageAmount > UGCSimpleCharacterSystem.GetHealth(self) then
|
|||
|
DamageAmount = UGCSimpleCharacterSystem.GetHealth(self)
|
|||
|
end
|
|||
|
|
|||
|
local GameState = UGCGameSystem.GameState
|
|||
|
GameState:UpdatePlayerDamage(PlayerKey, self.ID, DamageAmount)
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
function BP_MonsterBase:RemoveModifyDamageDelegation(Key)
|
|||
|
if self.ModifyDamageDelegation[Key] then
|
|||
|
self.ModifyDamageDelegation[Key] = nil
|
|||
|
return true
|
|||
|
end
|
|||
|
return false
|
|||
|
end
|
|||
|
|
|||
|
---@param Key string
|
|||
|
---@param DelegationFun fun(DamageAmount:float,DamageEvent:FDamageEvent,EventInstigator:AController,DamageCauser:AActor):float
|
|||
|
---@return bool
|
|||
|
function BP_MonsterBase:AddModifyDamageDelegationFun(Key, DelegationFun)
|
|||
|
if self.ModifyDamageDelegation[Key] then
|
|||
|
return false
|
|||
|
else
|
|||
|
self.ModifyDamageDelegation[Key] = DelegationFun
|
|||
|
return true
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
-- 获取封印 KillCount
|
|||
|
function BP_MonsterBase:GetSealKillCount()
|
|||
|
return 1
|
|||
|
end
|
|||
|
|
|||
|
-------------------------------RPCs-------------------------------
|
|||
|
|
|||
|
function BP_MonsterBase:GetAvailableServerRPCs()
|
|||
|
return
|
|||
|
"ReceiveOnMonsterDeath"
|
|||
|
-- "Client_MulticastRPC_RemoveAllSkillEffect"
|
|||
|
end
|
|||
|
|
|||
|
function BP_MonsterBase:Client_MulticastRPC_RemoveAllSkillEffect(CasterActor)
|
|||
|
local EffectSystemManager = require('Script.Manager.EffectSystemManager')
|
|||
|
EffectSystemManager.RemoveAllEffectOfActor(CasterActor)
|
|||
|
end
|
|||
|
|
|||
|
return BP_MonsterBase;
|