---@class BP_MonsterBoss_C:BP_MonsterAttack_C ---@field HealthWidget UWidgetComponent ---@field NarrationWidget UWidgetComponent --Edit Below-- local MonsterAttack = require('Script.Blueprint.Monster.BP_MonsterAttack') local BP_MonsterBoss = setmetatable( { HasBegunPlay = false, KilledPlayerNum = 0, SpawnMinionsHealthPercents = {0.8, 0.5, 0.3, 0.1}, SpawnedMinions = {}, }, { __index = MonsterAttack, __metatable = MonsterAttack } ) BP_MonsterBoss.BornTime = nil; function BP_MonsterBoss:GetReplicatedProperties() return "KilledPlayerNum", "bIsStun", "TargetPlayerKey" end function BP_MonsterBoss:ReceiveBeginPlayEx() MonsterAttack.ReceiveBeginPlayEx(self) if self:HasAuthority() then local PlayerStates = UGCGameSystem.GetAllPlayerState(false); local ServerTime = KismetSystemLibrary.GetGameTimeInSeconds(self) for i, v in pairs(PlayerStates) do if v then --if v.EasterEggsData[3] == nil then -- v.EasterEggsData[3] = {} --end --v.EasterEggsData[3].BeginTime = ServerTime end end self.BornTime = ServerTime; else EventSystem.SetTimer(self, function() self.NarrationWidget.Widget:UpdateKilledPlayerNum(self.KilledPlayerNum) end, 1.5) end end function BP_MonsterBoss:BPReceiveDamageEx(DamageAmount, DamageType, EventInstigator, DamageCauser) if self.bIsReplica then return end local CurHPSpawnThreshold = self.SpawnMinionsHealthPercents[1] if CurHPSpawnThreshold then local CurHP = UGCSimpleCharacterSystem.GetHealth(self) local MaxHP = UGCSimpleCharacterSystem.GetHealthMax(self) local HPPercent = CurHP / MaxHP if HPPercent <= CurHPSpawnThreshold then self:SpawnMinions(#UGCGameSystem.GetAllPlayerPawn() * 5) table.remove(self.SpawnMinionsHealthPercents, 1) end end UE.Log("[BP_MonsterBoss:BPReceiveDamageEx] %s: CurHealth=%.2f, MaxHealth=%.2f, DamageAmount=%.2f, EventInstigator=%s, Causer=%s", KismetSystemLibrary.GetObjectName(self), UGCSimpleCharacterSystem.GetHealth(self), UGCSimpleCharacterSystem.GetHealthMax(self), DamageAmount, KismetSystemLibrary.GetObjectName(EventInstigator), KismetSystemLibrary.GetObjectName(DamageCauser)) end function BP_MonsterBoss:SpawnMinions(SpawnNum) local MonsterClass = GameDataManager.GetAttackWaveCommonMonsterClass() for i = 1, SpawnNum do local SpawnLoc = VectorHelper.RandomVector(self:K2_GetActorLocation(), 1) local SpawnRot = VectorHelper.RandomRotatorYaw(self:K2_GetActorRotation()) local Monster = UGCGameSystem.SpawnActor(self, MonsterClass, SpawnLoc, SpawnRot, VectorHelper.ScaleOne(), nil) if Monster then local MaxHP = UGCSimpleCharacterSystem.GetHealthMax(self) / 10.0 UGCSimpleCharacterSystem.SetHealthMax(Monster, MaxHP) UGCSimpleCharacterSystem.SetHealth(Monster, MaxHP) UGCSimpleCharacterSystem.SetSpeedScale(Monster, 385 / 600) Monster.BossLevel = 1 Monster.AttackValue = self.AttackValue / 10.0 Monster.PhysicalDefense = self.PhysicalDefense / 10.0 Monster.DeadCoinPoint = 0.0 Monster.DeadKillPoint = 0.0 Monster.BaseHealthMax = MaxHP Monster.BaseAttackValue = Monster.AttackValue Monster.BasePhysicalDefense = Monster.PhysicalDefense Monster.BaseMaxWalkSpeed = 385 Monster.OnDeath:Add(self.OnMinionDeath, self) table.insert(self.SpawnedMinions, Monster) end end end function BP_MonsterBoss:OnMinionDeath(DeadMonster, KillerController, DamageCauser, KillingHitInfo, KillingHitImpulseDir, KillingHitDamageTypeID, DamageTypeClass, IsHeadShotDamage) for Index, Minion in pairs(self.SpawnedMinions) do if DeadMonster == Minion then self.SpawnedMinions[Index] = nil break end end end function BP_MonsterBoss:OnRep_KilledPlayerNum() if UE.IsValid(self.NarrationWidget.Widget) then self.NarrationWidget.Widget:UpdateKilledPlayerNum(self.KilledPlayerNum) end end function BP_MonsterBoss:ClientOnHealthChangedEx(CurrentHP, MaxHP) UE.Log("[BP_MonsterBoss:ClientOnHealthChangedEx] %s: CurHealth=%.2f, MaxHealth=%.2f", KismetSystemLibrary.GetObjectName(self), CurrentHP, MaxHP) if UE.IsValid(self.NarrationWidget.Widget) then self.NarrationWidget.Widget:UpdateOwnerHealth(CurrentHP, MaxHP) end if UE.IsValid(self.HealthWidget.Widget) then self.HealthWidget.Widget:UpdateOwnerHealth(CurrentHP, MaxHP) end end function BP_MonsterBoss:ReceiveOnMonsterDeath() MonsterAttack.ReceiveOnMonsterDeath(self) if self:HasAuthority() then else self.NarrationWidget.Widget:UpdateOwnerHealth(0, 100) self.HealthWidget.Widget:UpdateOwnerHealth(0, 100) end end function BP_MonsterBoss:GetDropRate() return 100 end function BP_MonsterBoss:ServerOnDeathEx(DeadMonster, KillerController, DamageCauser, KillingHitInfo, KillingHitImpulseDir, KillingHitDamageTypeID, DamageTypeClass, IsHeadShotDamage) MonsterAttack.ServerOnDeathEx(self, DeadMonster, KillerController, DamageCauser, KillingHitInfo, KillingHitImpulseDir, KillingHitDamageTypeID, DamageTypeClass, IsHeadShotDamage) -- 当 BOSS 死亡之后所有玩家的 BOSS 击杀数都加一 if DeadMonster == self then local PlayerStates = UGCGameSystem.GetAllPlayerState(false); -- BOSS 死亡掉落 local ChineseName = Tables.MonsterBaseConfig[DeadMonster.ID].ChineseName -- 检查一下有多少怪物 local Count = 0 local Diff = UGCGameSystem.GameState.GameDifficulty if Diff >= 4 then Diff = 4; end for i, v in pairs(Tables.GameFightStageConfig[Diff]) do Count = Count + v.MonsterNum.Boss end -- 如果当前 Boss == 最后一位 Boss local BossList = UGCGameSystem.GameState.BossList log_tree("[BP_MonsterBoss:OnSelfDeath] BossList = ", BossList) if DeadMonster.ID == BossList[#BossList] then EventSystem:SendEvent(EventType.OnSendGameEnd, "LastBossDefeated") end local ServerTime = KismetSystemLibrary.GetGameTimeInSeconds(self) local CostTime = ServerTime - self.BornTime for i, v in pairs(PlayerStates) do if v then v.KillCount.Boss = v.KillCount.Boss + 1 v.ArchiveData.TotalBossKilledTimes = v.ArchiveData.TotalBossKilledTimes + 1 ArchiveTable.Funcs[ArchiveTable.ArchiveType.EasterEggs](v, 3, CostTime); -- 计算当前彩蛋 3 if v.EasterEggsData[3] == nil then v.EasterEggsData[3] = {} v.EasterEggsData[3].BossCount = 1 else if v.EasterEggsData[3].BossCount == nil then v.EasterEggsData[3].BossCount = 0 end v.EasterEggsData[3].BossCount = v.EasterEggsData[3].BossCount + 1 end if v.EasterEggsData[3].BossCount == Count then local ServerTime = KismetSystemLibrary.GetGameTimeInSeconds(self) v.EasterEggsData[3].EndTime = ServerTime local BeginTime = v.EasterEggsData[3].BeginTime if BeginTime ~= nil then ArchiveTable.Funcs[ArchiveTable.ArchiveType.EasterEggs](v, 3, ServerTime - BeginTime) end end -- 计算总的掉落概率 local DropRate = 0 for _, c in pairs(ArchiveTable.BossDropItems[ChineseName]) do if c.DropRate ~= nil then DropRate = c.DropRate + DropRate end end local RandNum = math.random() if RandNum <= DropRate then local Val = math.random(1, 4) if v.ArchiveData.BossDropItems[ChineseName] == nil then v.ArchiveData.BossDropItems[ChineseName] = {} end if v.ArchiveData.BossDropItems[ChineseName][Val] == nil then v.ArchiveData.BossDropItems[ChineseName][Val] = 1 else v.ArchiveData.BossDropItems[ChineseName][Val] = v.ArchiveData.BossDropItems[ChineseName][Val] + 1 end end end end for Index, Minion in pairs(self.SpawnedMinions) do if Minion ~= nil and UE.IsValid(Minion) and Minion:IsAlive() then Minion:SetLifeSpan(2.0) end self.SpawnedMinions[Index] = nil end end end return BP_MonsterBoss;