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

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

  1. **引入基类**:
  • 使用`require`函数引入`ai_base`类,作为基础类。
  1. **定义`ai_dead`类**:
  • 使用`class`关键字定义了`ai_dead`类,并继承自`BASE`(即`ai_base`)。
  1. **构造函数 (`ctor`)**:
  • 构造函数接受一个`entity`参数,并设置`_type`属性为`eAType_DEAD`,表示死亡的行为。
  1. **`IsValid` 方法**:
  • 这个方法用于验证AI是否应该处于死亡状态。它首先调用基类的`IsValid`方法,然后检查实体是否死亡。
  1. **`OnEnter` 方法**:
    • 当AI组件进入激活状态时执行。如果基类的`OnEnter`方法返回`true`,则执行以下操作:
    • 重置`_fadeOut`和`_slowMotion`标志。
    • 检查并重置玩家的自动普通攻击状态。
    • 隐藏实体的称号节点。
    • 检查并重置玩家的超级模式状态。
    • 检查并重置骑乘状态。
    • 如果实体不是宠物或技能类型,播放死亡动作列表。
    • 锁定实体动画。
    • 处理同步RPC和发送死亡命令。
    • 处理玩家死亡后的界面逻辑,如复活界面和宠物状态。
    • 清理死亡实体的仇恨列表和战斗时间。
  1. **`OnLeave` 方法**: 当AI组件离开激活状态时执行。如果基类的`OnLeave`方法返回`true`,则解锁实体动画。

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

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

代码中的一些关键点:

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

`OnEnter` 方法的逻辑流程:

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

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

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

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

Lua 复制代码
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
相关推荐
张人玉1 小时前
人工智能——猴子摘香蕉问题
人工智能
草莓屁屁我不吃1 小时前
Siri因ChatGPT-4o升级:我们的个人信息还安全吗?
人工智能·安全·chatgpt·chatgpt-4o
小言从不摸鱼1 小时前
【AI大模型】ChatGPT模型原理介绍(下)
人工智能·python·深度学习·机器学习·自然语言处理·chatgpt
AI科研视界2 小时前
ChatGPT+2:修订初始AI安全性和超级智能假设
人工智能·chatgpt
霍格沃兹测试开发学社测试人社区2 小时前
人工智能 | 基于ChatGPT开发人工智能服务平台
软件测试·人工智能·测试开发·chatgpt
小R资源2 小时前
3款免费的GPT类工具
人工智能·gpt·chatgpt·ai作画·ai模型·国内免费
Karoku0663 小时前
【网站架构部署与优化】web服务与http协议
linux·运维·服务器·数据库·http·架构
artificiali5 小时前
Anaconda配置pytorch的基本操作
人工智能·pytorch·python
酱香编程,风雨兼程5 小时前
深度学习——基础知识
人工智能·深度学习
Lill_bin6 小时前
深入理解ElasticSearch集群:架构、高可用性与数据一致性
大数据·分布式·elasticsearch·搜索引擎·zookeeper·架构·全文检索