lua 游戏架构 之 游戏 AI (七)ai_dead

CSDN 2024-07-31 14:01:04 阅读 66

定义一个名为`ai_dead`的类,继承自`ai_base`类。这个类用于处理游戏中AI在死亡状态下的行为逻辑。以下是对代码的具体解释:

1. **引入基类**:

   - 使用`require`函数引入`ai_base`类,作为基础类。

2. **定义`ai_dead`类**:

   - 使用`class`关键字定义了`ai_dead`类,并继承自`BASE`(即`ai_base`)。

3. **构造函数 (`ctor`)**:

   - 构造函数接受一个`entity`参数,并设置`_type`属性为`eAType_DEAD`,表示死亡的行为。

4. **`IsValid` 方法**:

   - 这个方法用于验证AI是否应该处于死亡状态。它首先调用基类的`IsValid`方法,然后检查实体是否死亡。

5. **`OnEnter` 方法**:

     - 当AI组件进入激活状态时执行。如果基类的`OnEnter`方法返回`true`,则执行以下操作:     - 重置`_fadeOut`和`_slowMotion`标志。     - 检查并重置玩家的自动普通攻击状态。     - 隐藏实体的称号节点。     - 检查并重置玩家的超级模式状态。     - 检查并重置骑乘状态。     - 如果实体不是宠物或技能类型,播放死亡动作列表。     - 锁定实体动画。     - 处理同步RPC和发送死亡命令。     - 处理玩家死亡后的界面逻辑,如复活界面和宠物状态。     - 清理死亡实体的仇恨列表和战斗时间。

6. **`OnLeave` 方法**: 当AI组件离开激活状态时执行。如果基类的`OnLeave`方法返回`true`,则解锁实体动画。

7. **`OnLogic` 方法**: 逻辑更新方法。如果基类的`OnLogic`方法返回`true`,则根据时间间隔处理死亡逻辑,如淡出效果、实体销毁等。

8. **创建组件函数**: `create_component`函数用于创建`ai_dead`类的新实例,传入一个实体和一个优先级。

代码中的一些关键点:

- `IsDead()`:检查实体是否死亡。- `ShowTitleNode()`:显示或隐藏实体的称号节点。- `SuperMode()`:处理玩家的超级模式。- `OnRideMode()`:处理玩家的骑乘模式。- `PlayActionList()`:播放一系列动作。- `LockAni()`:锁定实体的动画。- `Show()`:控制实体的显示与隐藏。- `Destory()`:销毁实体。- `CanRelease()`:检查实体是否可以释放。

`OnEnter` 方法的逻辑流程:

- 调用基类的`OnEnter`方法,如果返回`true`,则继续。- 重置相关动画和攻击状态。- 隐藏称号节点。- 检查并重置超级模式和骑乘状态。- 播放死亡动作列表并锁定动画。- 发送死亡同步命令和处理复活界面逻辑。- 清理仇恨列表和战斗时间。

`OnLogic` 方法中,根据时间间隔处理死亡后的逻辑,如:

- 如果实体存活时间超过4秒,并且可以释放,则销毁实体。- 如果实体存活时间超过2秒,并且可以释放,则开始淡出效果。

整体而言,`ai_dead`类的目的是在AI实体死亡时,提供一套标准的行为和逻辑处理,确保游戏内死亡状态的表现和交互符合预期。

<code>

local require = require

local BASE = require("logic/entity/ai/ai_base").ai_base;

------------------------------------------------------

ai_dead = class("ai_dead", BASE);

function ai_dead:ctor(entity)

self._type = eAType_DEAD;

end

function ai_dead:IsValid()

if not BASE.IsValid(self) then return false; end

return self._entity:IsDead();

end

function ai_dead:OnEnter()

if BASE.OnEnter(self) then

self._fadeOut= false;

self._slowMotion= false;

local logic = game_get_logic();

if logic then

local player = logic:GetPlayer();

if player and player:GetHero() then

local hero = player:GetHero();

if hero then

if hero._autonormalattack then

if hero._guid == self._entity._guid then

hero._preautonormalattack = false;

hero._autonormalattack = false;

elseif self._entity._selected == self._entity._guid then

hero._preautonormalattack = false;

hero._autonormalattack = false;

elseif hero._follow then

if hero._follow._guid == self._entity._guid then

hero._preautonormalattack = false;

hero._autonormalattack = false;

end

end

end

end

end

end

self._entity:ShowTitleNode(false);

if self._entity:GetEntityType() == eET_Player then

--清神兵状态

if self._entity._superMode.valid then

local hero = game_get_player_hero()

if self._entity:IsPlayer() then

self._entity:SuperMode(false)

else

self._entity:OnSuperMode(false)

end

end

if self._entity:IsPlayer() then

g_game_context:ResetLeadMode()

local animation = g_game_context:GetSelectWeaponMaxAnimation()

if animation then

g_game_context:OnStuntAnimationChangeHandler(animation,false)

end

end

--清骑乘

local world = game_get_world()

if world and not world._syncRpc then

if self._entity:IsOnRide() then

self._entity:OnRideMode(false, true)

end

end

if self._entity._DIYSkill then

self._entity._DIYSkill:OnReset();

end

end

if self._entity:GetEntityType() ~= eET_Pet and self._entity:GetEntityType() ~= eET_Skill then

local alist = {}

table.insert(alist, {actionName = db_common.engine.defaultDeadAction, actloopTimes = 1})

table.insert(alist, {actionName = db_common.engine.defaultDeadLoopAction, actloopTimes = -1})

self._entity:PlayActionList(alist, 1);

end

self._entity:LockAni(true);

local logic = game_get_logic();

if logic then

local world = logic:GetWorld();

if world then

local syncRpc = world._syncRpc;

if not syncRpc then

-- send cmd

local entity = self._entity;

if entity and entity:GetEntityType() == eET_Monster and entity._spawnID > 0 then

local weaponID = g_game_context:IsInSuperMode() and 1 or 0

local damageRank = g_game_context:GetMapCopyDamageRank()

local args = { spawnPointID = entity._spawnID , pos = entity._curPos, weaponID = weaponID, damageRank = damageRank}

sbean.sync_privatemap_kill(args)

end

local hero = game_get_player_hero()

if hero then

hero:RemoveSummoned();

end

end

end

end

if self._entity:GetEntityType() == eET_Player then

if logic then

local player = logic:GetPlayer()

local hero = nil

if player then

hero = player:GetHero()

end

local logic = game_get_logic();

local world = logic:GetWorld()

local PetCount = player:GetPetCount()

for i = 1,tonumber(PetCount) do

local Pet = player:GetPet(i)

Pet:OnDead()

end

if g_db.db_get_is_open_revive_ui() then

if hero._guid == self._entity._guid then

if hero._killerId and hero._killerId < 0 then

--天雷复活界面

local killerID = math.abs(hero._killerId);

local guid = string.split(hero._guid, "|")

local playerId = tonumber(guid[2])

if killerID == playerId then

g_ui_mgr:OpenUI(eUIID_PlayerRevive)

g_ui_mgr:RefreshUI(eUIID_PlayerRevive, true)

end

else

g_logic:OpenReviveUI()

end

--log("eUIID_PlayerRevive")

local MercenaryCount = player:GetMercenaryCount();

for i = 1,tonumber(MercenaryCount) do

local Mercenary = player:GetMercenary(i)

Mercenary:OnDead()

end

end

else

if hero._guid == self._entity._guid and (game_get_map_type() == g_ARENA_SOLO or game_get_map_type() == g_TAOIST) then

g_game_context:SetAutoFight(false)

local MercenaryCount = player:GetMercenaryCount();

for i = 1,tonumber(MercenaryCount) do

local Mercenary = player:GetMercenary(i)

if not Mercenary:IsDead() then

local camera = logic:GetMainCamera()

hero:DetachCamera()

Mercenary:AttachCamera(camera);

camera:UpdatePos(Mercenary._curPosE);

break;

end

end

end

end

if world and not world._syncRpc then

self._entity:ClsHorseAi();

end

end

end

if self._entity._forceAttackTarget then

self._entity._forceAttackTarget = nil;

end

if self._entity:GetEntityType() == eET_Mercenary then

self._entity._deadTimeLine = g_get_GMTtime(game_get_time())

if logic then

local player = logic:GetPlayer()

local hero = nil

if player then

hero = player:GetHero()

end

local logic = game_get_logic();

local world = logic:GetWorld()

if world._fightmap then

if hero:IsDead() and (game_get_map_type() == g_ARENA_SOLO or game_get_map_type() == g_TAOIST) then

local guid1 = string.split(hero._guid, "_")

local guid2 = string.split(self._entity._guid, "_")

if tonumber(guid1[2]) == tonumber(guid2[3]) then

local MercenaryCount = player:GetMercenaryCount();

for i = 1,tonumber(MercenaryCount) do

local Mercenary = player:GetMercenary(i)

if not Mercenary:IsDead() then

local camera = logic:GetMainCamera()

self._entity:DetachCamera()

Mercenary:AttachCamera(camera);

camera:UpdatePos(Mercenary._curPosE);

break;

end

end

end

end

end

end

self._entity:ClsEnmities();

end

if self._entity:GetEntityType() == eET_Player or self._entity:GetEntityType() == eET_Mercenary then

self._entity:ClearFightTime();

end

if self._entity:GetEntityType() ~= eET_Player and self._entity:GetEntityType() ~= eET_Mercenary then

--self._entity:SetHittable(false);

end

if self._entity:GetEntityType() == eET_Pet then

local world = game_get_world();

local player = game_get_player()

if world and not world._syncRpc then

if self._entity._hoster then

local curFightSP = self._entity._hoster:GetFightSp()

self._entity._hoster:UpdateFightSpCanYing(curFightSP - 1)

local index = player:GetPetIdx(self._entity._guid)

if index > 0 then

player:RmvPet(index)

end

end

end

end

return true;

end

return false;

end

function ai_dead:OnLeave()

if BASE.OnLeave(self) then

self._entity:LockAni(false);

return true;

end

return false;

end

function ai_dead:OnLogic(dTick)

if BASE.OnLogic(self, dTick) then

if dTick > 0 then

if self._timeTick > 4000 then

if self._entity:CanRelease() then

self._entity:Destory()

end

elseif self._timeTick > 2000 then

if self._entity:CanRelease() then

if not self._fadeOut then

self._fadeOut = true;

self._entity:Show(false, true, 2000);

end

end

end

if self._entity:GetEntityType() == eET_Pet or self._entity:GetEntityType() == eET_Skill then

if self._entity:CanRelease() then

self._entity:Destory()

end

end

end

return true;

end

return false;

end

function create_component(entity, priority)

return ai_dead.new(entity, priority);

end

 



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。