当前位置: 代码网 > it编程>前端脚本>Python > lua 游戏架构 之 游戏 AI (七)ai_dead

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

2024年08月01日 Python 我要评论
`ai_dead`类的目的是在AI实体死亡时,提供一套标准的行为和逻辑处理,确保游戏内死亡状态的表现和交互符合预期。

定义一个名为`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实体死亡时,提供一套标准的行为和逻辑处理,确保游戏内死亡状态的表现和交互符合预期。



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


 

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com