赞
踩
这段Lua脚本定义了一个名为 `ai_autofight_find_way` 的类,继承自 `ai_base` 类。
这个类用于处理游戏中AI在自动战斗模式下寻找路径的逻辑。以下是对代码的具体解释:
1. **引入基类**:
- 使用 `require` 函数引入 `ai_base` 类,作为基础类。
2. **定义 `ai_autofight_find_way` 类**:
- 使用 `class` 关键字定义了 `ai_autofight_find_way` 类,并继承自 `BASE`(即 `ai_base`)。
3. **构造函数 (`ctor`)**:
- 构造函数接受一个 `entity` 参数,并设置 `_type` 属性为 `eAType_AUTOFIGHT_FIND_WAY`,表示自动战斗中寻找路径的行为。
- 初始化 `_target` 为 `nil`,用于后续存储找到的目标。
4. **`IsValid` 方法**:
5. **`OnEnter` 方法**:
- 当AI组件进入激活状态时执行。根据当前地图类型和条件,计算目标位置并使实体移动到该位置。
6. **`OnLeave` 方法**:
- 当AI组件离开激活状态时执行。当前实现中直接返回 `true`。
7. **`OnUpdate` 方法**:
- 每帧调用,用于更新AI状态。如果基类的 `OnUpdate` 方法返回 `true`,则当前方法也返回 `true`。
8. **`OnLogic` 方法**:
- 逻辑更新方法,如果基类的 `OnLogic` 方法返回 `true`,则当前方法返回 `false`,表示只执行一次。
9. **创建组件函数**:
- `create_component` 函数用于创建 `ai_autofight_find_way` 类的新实例,传入一个实体和一个优先级。
代码中的一些关键点:
这个脚本为游戏中的AI提供了一个自动战斗中寻找路径的基础框架,可以根据具体游戏的需求进行扩展和修改。以下是一些具体的逻辑处理:
整体而言,这个类的目的是在自动战斗模式下,根据游戏世界的当前状态和配置,为AI实体找到合适的移动路径。
重点解释一下 OnEnter:
- function ai_autofight_find_way:OnEnter()
- if BASE.OnEnter(self) then
- local entity = self._entity;
- local radius = entity:GetPropertyValue(ePropID_alertRange);
- local logic = game_get_logic();
- local world = game_get_world();
- if world then
- -- 如果世界配置中有自动战斗半径,则使用该值
- if world._cfg.autofightradius then
- radius = world._cfg.autofightradius;
- end
-
- -- 根据不同的地图类型执行不同的逻辑
- if world._mapType == g_BASE_DUNGEON or world._mapType == g_ACTIVITY or ... then
- -- 检查所有掉落物品,如果物品处于激活状态,则移动到该物品位置
- for k,v in pairs(world._ItemDrops) do
- if v and v:GetStatus() == eSItemDropActive then
- local _pos = logic_pos_to_world_pos(v._curPos);
- entity:MoveTo(_pos);
- return false; -- 移动到物品位置后,退出函数
- end
- end
-
- -- 如果地图类型是开放区域,并且有怪物刷新点或当前活动区域
- if world._openType == g_FIELD then
- -- 寻找一个有活着的怪物的刷新点
- local _pos = nil;
- local isfind = false;
- for k1,v1 in pairs(world._curArea._spawns) do
- for k2,v2 in pairs(v1._monsters) do
- if not v2:IsDead() then
- isfind = true;
- break;
- end
- end
- if isfind then
- _pos = v1._cfg.pos;
- break;
- end
- end
- -- 如果没有找到有活着的怪物的刷新点,使用第一个刷新点的位置
- if not _pos then
- _pos = world._curArea._spawns[1]._cfg.pos;
- end
-
- -- 计算实体当前位置到刷新点或地图增益点的距离
- local dist = vec3_dist(entity._curPos,world_pos_to_logic_pos(_pos));
- local mindist = dist;
-
- -- 寻找最近的地图增益点
- for k,v in pairs(world._mapbuffs) do
- if v and v:GetStatus() == 1 then
- local distbuff = vec3_dist(v._curPos,entity._curPos);
- if distbuff < mindist and distbuff < db_common.droppick.AutoFightMapbuffAutoRange then
- mindist = distbuff;
- _pos = logic_pos_to_world_pos(v._curPos);
- end
- end
- end
-
- -- 移动实体到计算出的位置
- entity:MoveTo(_pos);
- end
- -- 其他地图类型的逻辑...
- elseif world._mapType == g_FIELD or world._mapType == g_Life then
- -- 对于其他地图类型,寻找最近的地图增益点并移动实体
- -- ...
- end
- end
-
- return false; -- 如果没有找到目标位置或执行了移动逻辑,则返回false
- end
-
- return false; -- 如果没有调用基类的OnEnter或基类返回false,则返回false
- end

在 OnEnter
方法中,首先调用基类的 OnEnter
方法,如果它返回 false
,则直接返回 false
。如果基类的 OnEnter
方法返回 true
,则继续执行以下逻辑:
radius
。g_BASE_DUNGEON
、g_ACTIVITY
等地图类型,会检查所有物品掉落点,寻找激活的物品并移动到该位置。g_FIELD
),会寻找有活着的怪物的刷新点或最近的地图增益点,并移动实体到该位置。vec3_dist
函数计算实体当前位置到目标位置的距离,并根据这个距离来确定是否移动实体。entity:MoveTo(_pos)
方法移动实体到该位置,然后返回 false
退出函数。false
。整体而言,OnEnter
方法的目的是确定AI在自动战斗模式下应该移动到哪个位置,并执行移动操作。
全部代码实现:
- ----------------------------------------------------------------
- module(..., package.seeall)
-
- local require = require
-
- local BASE = require("logic/entity/ai/ai_base").ai_base;
-
-
- ------------------------------------------------------
- ai_autofight_find_way = class("ai_autofight_find_way", BASE);
- function ai_autofight_find_way:ctor(entity)
- self._type = eAType_AUTOFIGHT_FIND_WAY;
- self._target = nil;
- end
-
- function ai_autofight_find_way:IsValid()
- local entity = self._entity;
- if not entity._AutoFight then
- return false;
- end
-
- if entity:IsDead() or not entity:CanAttack() then
- return false;
- end
-
- if entity._behavior:Test(eEBPrepareFight) then
- return false;
- end
-
- if entity._behavior:Test(eEBDisAttack) then
- return false;
- end
-
- local radius = entity:GetPropertyValue(ePropID_alertRange);
-
- local world = game_get_world();
- if world then
- if world._cfg.autofightradius then
- radius = world._cfg.autofightradius;
- end
-
- local target = entity._alives[2][1]; -- 敌方
- if entity._alives[3][1] then--中立
- local trap = entity._alives[3][1];
- if trap.entity and trap.entity._traptype == eSTrapActive then
- target = entity._alives[3][1];
- end
- end
-
- if target then
- if target.dist < radius then
- if target.entity._groupType == eGroupType_N and target.dist > db_common.droppick.AutoFightMapbuffAutoRange then
- else
- return false;
- end
- end
- else
- if world._mapType == g_TOURNAMENT then
- return false;
- end
- end
-
- if world._mapType == g_BASE_DUNGEON or world._mapType == g_ACTIVITY or world._mapType == g_FACTION_DUNGEON or world._mapType == g_TOWER or world._mapType == g_WEAPON_NPC or world._mapType == g_RIGHTHEART or world._mapType == g_ANNUNCIATE or world._mapType == g_FIGHT_NPC or world._mapType == g_Pet_Waken then
- if world._openType == g_FIELD then
- if #world._spawns == 0 and not world._curArea then
- return false
- end
- else
- local spawnID = math.abs(g_game_context:GetDungeonSpawnID())
- if spawnID == 0 then
- return false
- end
-
- local dist = nil;
- if spawnID ~= 0 then
- spawnPointID = db_spawn_area[spawnID].spawnPoints[1]
- _pos = db_spawn_point[spawnPointID].pos
- dist = vec3_dist(entity._curPos,world_pos_to_logic_pos(_pos))
- if dist and dist < 100 then
- return false
- end
- end
- end
- elseif world._mapType == g_FIELD or world._mapType == g_Life then
- if entity._PVPStatus ~= g_PeaceMode then
- return false;
- end
-
- local dist = vec3_dist(entity._curPos,entity._AutoFight_Point)
- if dist < radius then
- return false;
- end
-
- local value = g_game_context:getAutoFightRadius()
- if value and value == g_OneMap then
- return false;
- end
- else -- TODO
- return false;
- end
- end
-
- return true;
- end
-
- function ai_autofight_find_way:OnEnter()
- if BASE.OnEnter(self) then
- local entity = self._entity;
- local radius = entity:GetPropertyValue(ePropID_alertRange)
- local logic = game_get_logic();
- local world = game_get_world();
- if world then
- if world._cfg.autofightradius then
- radius = world._cfg.autofightradius
- end
- if world._mapType == g_BASE_DUNGEON or world._mapType == g_ACTIVITY or world._mapType == g_FACTION_DUNGEON or world._mapType == g_TOWER or world._mapType == g_WEAPON_NPC or world._mapType == g_RIGHTHEART or world._mapType == g_ANNUNCIATE or world._mapType == g_FIGHT_NPC or world._mapType == g_Pet_Waken then
- for k,v in pairs(world._ItemDrops) do
- if v and v:GetStatus() == eSItemDropActive then
- local _pos = logic_pos_to_world_pos(v._curPos)
- entity:MoveTo(_pos)
- return false;
- end
- end
- if world._openType == g_FIELD then
- if #world._spawns > 0 or world._curArea then
- local _pos = nil;
- local isfind = false
- for k1,v1 in pairs(world._curArea._spawns) do
- for k2,v2 in pairs(v1._monsters) do
- if not v2:IsDead() then
- isfind = true;
- break;
- end
- end
- if isfind then
- _pos = v1._cfg.pos;
- break;
- end
- end
- if not _pos then
- _pos = world._curArea._spawns[1]._cfg.pos
- end
- --local _pos = world._curArea._spawns[1]._cfg.pos
- local dist = vec3_dist(entity._curPos,world_pos_to_logic_pos(_pos))
- local mindist = dist
- for k,v in pairs(world._mapbuffs) do
- if v and v:GetStatus() == 1 then
- local distbuff = vec3_dist(v._curPos,entity._curPos)
- if distbuff < mindist and distbuff < db_common.droppick.AutoFightMapbuffAutoRange then
- mindist = distbuff
- _pos = logic_pos_to_world_pos(v._curPos)
- end
- end
- end
- entity:MoveTo(_pos)
- end
- else
- local _pos = nil
- local spawnID = math.abs(g_game_context:GetDungeonSpawnID())
- local dist = 99999999999;
- if spawnID ~= 0 then
- spawnPointID = db_spawn_area[spawnID].spawnPoints[1]
- _pos = db_spawn_point[spawnPointID].pos
- dist = vec3_dist(entity._curPos,world_pos_to_logic_pos(_pos))
- end
-
- local mindist = dist
- local isspawn = true
- for k,v in pairs(world._mapbuffs) do
- if v and v:GetStatus() == 1 then
- local distbuff = vec3_dist(v._curPos,entity._curPos)
- if distbuff < mindist and distbuff < db_common.droppick.AutoFightMapbuffAutoRange then
- mindist = distbuff
- isspawn = false;
- _pos = logic_pos_to_world_pos(v._curPos)
- end
- end
- end
- if mindist < 150 and isspawn and g_game_context:GetDungeonSpawnID() < 0 then
- g_game_context:SetDungeonSpawnID(0);
- _pos = nil;
- end
- if _pos then
- entity:MoveTo(_pos)
- end
- end
- elseif world._mapType == g_FIELD or world._mapType == g_Life then
- for k,v in pairs(world._mapbuffs) do
- if v and v:GetStatus() == 1 then
- local distbuff = vec3_dist(v._curPos,entity._AutoFight_Point)
- if distbuff < radius and distbuff < db_common.droppick.AutoFightMapbuffAutoRange then
- local _pos = logic_pos_to_world_pos(v._curPos)
- entity:MoveTo(_pos)
- return false;
- end
- end
- end
- end
- end
-
- return false;
- end
-
- return false;
- end
-
- function ai_autofight_find_way:OnLeave()
- if BASE.OnLeave(self) then
-
- return true;
- end
-
- return false;
- end
-
- function ai_autofight_find_way:OnUpdate(dTime)
- if BASE.OnUpdate(self, dTime) then
- return true;
- end
-
- return false;
- end
-
- function ai_autofight_find_way:OnLogic(dTick)
- if BASE.OnLogic(self, dTick) then
- return false; -- only one frame
- end
-
- return false;
- end
-
- function create_component(entity, priority)
- return ai_autofight_find_way.new(entity, priority);
- end
-

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。