local UIUtils = require("UI.Utils") local Reactive = require("Core.Reactive") local ERoleState = import("EBusyRoleState") local EBusyItemEffectType = import("EBusyItemEffectType") local GameplayStatics = import ("GameplayStatics") local GetGameplayTag = require("GamePlay.Utils").GetGameplayTag local BusyActorManagerSubSystem = import("BusyActorManagerSubSystem") local GamePlayUtils = require("GamePlay.Utils") local KismetMathLibrary = import("KismetMathLibrary") local LevelItemRewardClass = import("LevelItemReward") --- @class BusyRole local Role={ movement_watcher = nil, interacte_item = nil } local PickAbilityTag = "Ability.Role.Pick" local RecoverAbilityTag = "Ability.Role.Recover" local ConsumeAbilityTag = "Ability.Role.AttributeConsume" local RollAbilityTag = "Ability.Role.Roll" -- 私有函数 -- 采集相关 --- @param role BusyRole --- @param pick_targer BusyLevelItem local function ResetPickWatcher(role, pick_targer) if role.pick_watcher ~= nil then role.pick_watcher:Destroy() end role.pick_watcher = Reactive.Watcher(function() if not pick_targer:IsAlive() then role.pick_watcher:Destroy() role.pick_watcher = nil role.carried_item_id = pick_targer:GetItemID() end end) end --- 存储正在搬运的物品 local function StoreCarriedItem(role) -- if not role.carried_item_id then return end -- local sub_system = BusyActorManagerSubSystem.Get(role) -- local bonfire = sub_system:GetNearestBonfire() -- if bonfire:StoreItem(role.carried_item_id) then -- role.carried_item_id = nil -- end end function Role:ctor() self.pick_timer = nil self.carried_item_id = nil self.time_limited_tags = {} self.pick_watcher = nil -- 监听正在采集物品的状态 self.proxy = Reactive.ReactiveProperty({ state = ERoleState.BonfireIdle, is_alive = true, }) end function Role:ReceiveBeginPlay() self.bCanEverTick = false self.Inventory:DepositItems(200001, 2) self.movement_watcher = Reactive.Watcher(function() self:UpdateRoleState() end) end function Role:ReceiveEndPlay() print(self, "Role:ReceiveEndPlay") end function Role:ReceiveSetRole(_) self:TryActiveAbility(ConsumeAbilityTag, nil) UIUtils.ShowWidget(self, "RoleState", {role=self}) end function Role:UpdateRoleState() -- 在auto run中访问Reactive Property的值,会导致多次调用,有性能隐患 local role_state = Reactive.RawGet(self.proxy, "state") local move_proxy = self.Movement.proxy if move_proxy.isIdle then if role_state == ERoleState.Searching or role_state == ERoleState.PickFinished then self.proxy.state = ERoleState.BackBonfire self.Movement:BackBonfire() elseif role_state == ERoleState.BackBonfire then -- StoreCarriedItem(self) self.proxy.state = ERoleState.BonfireIdle end else if role_state == ERoleState.BonfireIdle then self.proxy.state = ERoleState.Searching end end print("old", role_state, "new", Reactive.RawGet(self.proxy, "state"), move_proxy.isIdle) end function Role:StartPick(level_item) local GameplayEventData = import("GameplayEventData") local EventData = GameplayEventData() EventData.Instigator = self EventData.Target = level_item self.proxy.state = ERoleState.Picking self:TryActiveAbility(PickAbilityTag, EventData) -- ResetPickWatcher(self, level_item) end function Role:OnTouch(_) local role_proxy = self.proxy if role_proxy.state == ERoleState.BonfireIdle then local pc = GameplayStatics.GetPlayerController(self:GetWorld(), 0) local world_x, world_y = pc:convertCursorToWorldPosition() role_proxy.state = ERoleState.Searching self.Movement:SetDestination(world_x, world_y) else print("nothing") end end function Role:OnOverlapBegin(OverlappedComp, OtherActor, OtherComp, OtherBodyIndex, bFromSweep, SweepResult) if KismetMathLibrary.ClassIsChildOf(OtherActor:GetClass(), LevelItemRewardClass) then self.Inventory:DepositItems(OtherActor.RewardID, 1) OtherActor:ConditionalBeginDestroy() else if self.proxy.state ~= ERoleState.Searching then return end self.proxy.state = ERoleState.Picking self.Movement:Stop() self:StartPick(OtherActor) end end --- 使用翻滚技能 function Role:UseRollSkill() self:TryActiveAbility(RollAbilityTag, nil) end -- 接口 function Role:GetPickEffect() return self.RoleConfig.PickEffect end function Role:GetHealthPercent() local current_health = self.LuaRoleAttribute.Health or 0 return current_health / self.RoleConfig.Health end function Role:GetHungerPercent() return self.LuaRoleAttribute.Hunger / self.RoleConfig.Hunger end function Role:GetHungerConsumeSpeed() if self.time_limited_tags["SkillRole"] ~= nil then return self.RoleConfig.HungerConsumeSpeed * 8 else return self.RoleConfig.HungerConsumeSpeed end end function Role:GetSpeed() return self.LuaRoleAttribute.MoveSpeed end function Role:GetMoveDirection() return self.Movement.proxy.direction end --- 返回即将消耗的饥饿值和生命值 function Role:CalcRealChangeByHunger(value) local config = self.RoleConfig local fixed_change, extra_health_need = 0, 0 local cost_rate = config.HealthConsumeSpeed / config.HungerConsumeSpeed local remain_hunger = self.LuaRoleAttribute.Hunger + value if remain_hunger < 0 then fixed_change = remain_hunger extra_health_need = remain_hunger * cost_rate elseif remain_hunger > self.RoleConfig.Hunger then fixed_change = remain_hunger - self.RoleConfig.Hunger end return value - fixed_change, self:CalcRealChangeByHealth(extra_health_need) end function Role:CalcRealChangeByHealth(value) if value == 0 then return 0 end local fixed_change = 0 local remain_health = self.LuaRoleAttribute.Health + value if remain_health < 0 then fixed_change = remain_health elseif remain_health > self.RoleConfig.Health then fixed_change = remain_health - self.RoleConfig.Health end return value - fixed_change end return Class(nil, nil, Role)