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; |