支持HW团队,就支付宝领取下面的红包吧!(2018年3月31前,就几毛,也会几块,可以和其他红包叠加使用),你领取消费,HW有奖励。红包使用无条件限制,有条件请注意是不是有病毒。

小伙伴们,给大家发红包喽!人人可领,领完就能用。祝大家领取的红包金额大大大!#吱口令#长按复制此消息,打开支付宝就能领取!er1OEj73Uj

登入 注册 | 验证
| 搜索
HelloWorld论坛 : > 计算机科学、技术、教学> 编程专题> 开源免费项目> [转]Mangos服务器的游戏对象和AI系统
 
 
 
 
类别:游戏 阅读:4483 评论:0 时间:六月 13, 2013, 4:32 p.m. 关键字:AI MaNGOS

 

主要的几个对象类
1.Object类主要功能
1) InWorld判断和操作
2) GUID
Mangos的每个对象都有唯一的GUID,每类GUID的最大值是保存在数据库中,初始化时候从数据库加载。Mangos这样做还是很奢侈的,国内服务器可能都存在合服需求,所以国内服务器操持角色ID不同即可。可能要合服的服务器在开服的时候要把的角色ID范围要规划好(天龙八部的角色ID的最大值是保存在数据库中的)。国内服务器中对于重要物品、宠物可能需要唯一的ID,可以考虑角色ID + 物品、宠物id来实现。uint32应该够用了,但是也要限制重要物品的种类和数量。
3) Object类型TypeId
enum TypeID
{
TYPEID_OBJECT = 0,
TYPEID_ITEM = 1,
TYPEID_CONTAINER = 2,
TYPEID_UNIT = 3,
TYPEID_PLAYER = 4,
TYPEID_GAMEOBJECT = 5,
TYPEID_DYNAMICOBJECT = 6,
TYPEID_CORPSE = 7
};
4) 网络包发送SendUpdateToPlayer
5) 基本状态组包Values、OutOfRange、Movement UpdateBlock等
6) Int, UInt, float等标记数据设置、加载、访问Get/SetXXXValue、SetFlag
union
{
int32 *m_int32Values;
uint32 *m_uint32Values;
float *m_floatValues;
};
Object有很多数据、状态以数组形式存储,访问时候通过类型和标记定位。
7) 任务判断接口hasQuest
2.Item类主要功能
1) 创建和复制Create/CloneItem
2) 所有者Owner(Player)
3) 数据库存取SaveTo/LoadFromDB
Mangos的每个Item在数据中是作为一条记录保存的,一般国内网游是打包保存在玩家记录里面,国内网游的做法在数据库效率上要高很多。
4) 绑定Binding、损坏Broken、是否可交易CanBeTrade、叠放数量、是否装备等一般道具属性
5) 在包中的位置Bag、Slot
6) 增强状态和时效Enhancement
7) Timer更新
8) 状态更新和广播State
9) 技能和魔法相关Skill/Spell
10) 任务相关hasQuest
3.Bag类主要功能
1) 增加、删除、得到某位置的道具Store/RemoveItem
2) 空间IsEmpty、GetFreeSlots
3) 数据库存取SaveTo/LoadFromDB
4) 组包更新BuildCreateUpdateBlockForPlayer
4.WorldObject类主要功能
1) 位置和朝向Relocate、SetOrientation
2) 附近空间位置GetClosePoint
3) 所在地图、区域和地区GetMapId、GetZoneId、GetAreaId
4) 名字GetName
5) 和其它WorldObject位置、角度等关系IsWithinDist、IsInRange
6) 发送网络消息SendMessageToSet
7) 发送聊天、喊叫等消息MonsterSay、MonsterYellToZone
8) 对玩家来说是否可见isVisibleFor
9) 召唤Creature,SummonCreature
5.Unit类主要功能
Unit类是很复杂的一个类,改类具有很多属性和方法,实现了游戏中Player,Creature等主要功能。
1) 渐变状态GetDiminishing
2) 战斗相关(计时器、攻击对象、停止等)setAttackTimer、Attack、getVictim、SendMeleeAttackStop
3) 单元状态addUnitState
4) 等级、种族、职业、装甲、血量、伤害能力等属性getLevel、getGender、getRace、GetArmor、GetHealth、GetPower
5) 友好、敌对等阵营关系IsHostileTo、IsFriendlyTo
6) 站立、行走、骑乘、战斗、飞行、水下、恐惧、死亡等状态getStandState、IsMounted、DeathState
7) 技能和伤害处理DealDamage、MeleeSpellHitResult、GetWeaponSkillValue
8) 类型(商店、银行、飞行点、行会、拍卖行等)isVendor、isBanker
9) 施展法术CastSpell
10) 光环状态和特效以及数值影响HasAura、RemoveAura
11) 广播伤害、攻击状态等消息SendAttackStateUpdate、SendSpellMiss
12) 主人、召唤者、宠物等信息GetOwnerGUID、SetCharmerGUID、GetPet
13) 状态更新广播stat system
14) 可见性处理Visibility system
15) 威胁值处理Threat related methods
16) DynamicObject对象和GameObject对象的附加GetDynObject
17) event处理m_Events
18) MotionMaster
Unit类设计得过大,还包含了战斗、技能、伤害处理、光环状态影响等这些比较复杂的功能模块。
6.Creature类主要功能
1) 加入到世界
2) 加载装备
3) 数据库存取
4) 类型,是否是车辆、宠物、图腾、精英等
5) 能力,能否行走、游泳、飞行
6) 对技能免疫
7) AI和脚本
8) 售卖的道具
9) 状态更新
10) 对话内容
11) 聊天、喊叫
12) 战斗行为,寻求帮助
13) 重生处理
14) 任务相关
7.Player类主要功能
1) 加入到世界
2) 传送
3) 更新
4) 社会关系
5) 飞机
6) 位置
7) 宠物
8) 聊天
9) 装备、背包和仓库
10) 增强状态
11) 完整的任务处理
12) 数据库存取
13) 邮件
14) 技能
15) 天赋
16) 声望
17) 战场
18) 战斗状态和模式更新
19) 竞技场
20) 移动处理
21) 副本
22) 组队
Player类是继Unit类后另外一个很大的类,实现和很多功能。我现在很佩服Mangos服务器的程序员的水平了,这么多功能,居然一个类搞定。这样的代码对后继维护和修改者绝对是噩梦。
其它类比较小,略过。 

三、CreatureAI
CreatureAI这个类并不大,构造函数要传入一个Creature的指针,然后就是20来个接口函数。
构造函数:
explicit CreatureAI(Creature* creature) : m_creature(creature) {}
接口函数不多,可以全部列出来:
// Called if IsVisible(Unit *who) is true at each *who move, reaction at visibility zone enter
virtual void MoveInLineOfSight(Unit *) {}
// Called for reaction at enter to combat if not in combat yet (enemy can be NULL)
virtual void EnterCombat(Unit* /*enemy*/) {}
// Called for reaction at stopping attack at no attackers or targets
virtual void EnterEvadeMode() {}
// Called at reaching home after evade
virtual void JustReachedHome() {}
// Called at any heal cast/item used (call non implemented)
virtual void HealBy(Unit * /*healer*/, uint32 /*amount_healed*/) {}
// Called at any Damage to any victim (before damage apply)
virtual void DamageDeal(Unit * /*done_to*/, uint32 & /*damage*/) {}
// Called at any Damage from any attacker (before damage apply)
// Note: it for recalculation damage or special reaction at damage
// for attack reaction use AttackedBy called for not DOT damage in Unit::DealDamage also
virtual void DamageTaken(Unit * /*done_by*/, uint32 & /*damage*/) {}
// Called when the creature is killed
virtual void JustDied(Unit *) {}
// Called when the creature kills a unit
virtual void KilledUnit(Unit *) {}
// Called when the creature summon successfully other creature
virtual void JustSummoned(Creature* ) {}
virtual void SummonedCreatureDespawn(Creature* /*unit*/) {}
// Called when hit by a spell
virtual void SpellHit(Unit*, const SpellEntry*) {}
// Called when spell hits creature's target
virtual void SpellHitTarget(Unit*, const SpellEntry*) {}
// Called when the creature is target of hostile action: swing, hostile spell landed, fear/etc)
virtual void AttackedBy(Unit* attacker);
// Called when creature is spawned or respawned (for reseting variables)
virtual void JustRespawned() {}
// Called at waypoint reached or point movement finished
virtual void MovementInform(uint32 /*MovementType*/, uint32 /*Data*/) {}
// Called at text emote receive from player
virtual void ReceiveEmote(Player* /*pPlayer*/, uint32 /*text_emote*/) {}
// Called when creature attack expected (if creature can and no have current victim)
// Note: for reaction at hostile action must be called AttackedBy function.
virtual void AttackStart(Unit *) {}
// Is unit visible for MoveInLineOfSight
virtual bool IsVisible(Unit *) const { return false; }
// Called when victim entered water and creature can not enter water
virtual bool canReachByRangeAttack(Unit*) { return false; }
// Called at World update tick
virtual void UpdateAI(const uint32 /*diff*/) {}
可以看到,大部分接口是事件触发和消息通知。UpdateAI我放到最后,这个和别的接口函数不同,是负责AI状态的更新处理。

以CreatureAI为基类,派生出了PetAI、CreatureEventAI、GuardAI、ReactorAI、AggressAI、TotemAI和NullCreatureAI 7类基本AI。Creature的AIM_Initialize()函数,对AI进行初始化,根据Creature的类型选择不同的AI。值得提出的是,Mangos还支持ScriptAI,对于非宠物类的生物支持扩展脚本AI。Mangos的脚本系统我还没有怎么看,有空研究下。
可以看到Mangos的AI设计还是比较传统的,Creature类相当于身体和物理存在,干很多“傻大粗”的事情;AI相当于Creature的大脑,对事件进行响应和处理,指挥着身体物理存在进行反应。
下面可以看下宠物AI的一段代码:

void PetAI::MoveInLineOfSight(Unit *u) //有单位进入宠物视野
{
if( !m_creature->getVictim() && m_creature->GetCharmInfo() &&
m_creature->GetCharmInfo()->HasReactState(REACT_AGGRESSIVE) &&
u->isTargetableForAttack() && m_creature->IsHostileTo( u ) &&
u->isInAccessablePlaceFor(m_creature))
{ //好多判断:不是我已有的攻击目标,并且我是攻击性的,并且我可以攻击此单位,并且单位是我的敌对方,并且我能够得着它
float attackRadius = m_creature->GetAttackDistance(u);
if(m_creature->IsWithinDistInMap(u, attackRadius) && m_creature->GetDistanceZ(u) <= CREATURE_Z_ATTACK_RANGE) //在我的攻击范围内
{
if(m_creature->IsWithinLOSInMap(u)) //在我的视野中
{
AttackStart(u); //攻击开始消息
u->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); //去掉我的有隐身状态(有的话)
}
}
}
}
下面看看AttackStart干了什么:
void PetAI::AttackStart(Unit *u)
{
if(!u || (m_creature->isPet() && ((Pet*)m_creature)->getPetType() == MINI_PET)) //一些保护
return;
if(m_creature->Attack(u,true)) //攻击成功
{
m_creature->clearUnitState(UNIT_STAT_FOLLOW); //清除我的跟随状态
m_creature->GetMotionMaster()->MoveChase(u); //通过MotionMaster修改移动类型为Chase,并开始追。MotionMaster的分析见下面
inCombat = true;
}
}
四、MotionMaster
在Unit类中还有个MotionMaster成员,Creature在初始化AI的时候,对MotionMaster进行初始化。MotionMaster维护一个移动的列表并负责不同移动类型的生成。具体的移动类型控制Creature的移动。
下面是MotionMaster生成不同移动类型的接口函数:
void MoveIdle();
void MoveTargetedHome();
void MoveFollow(Unit* target, float dist, float angle);
void MoveChase(Unit* target, float dist = 0.0f, float angle = 0.0f);
void MoveConfused();
void MoveFleeing(Unit* enemy, uint32 time = 0);
void MovePoint(uint32 id, float x,float y,float z);
void MoveSeekAssistance(float x,float y,float z);
void MoveSeekAssistanceDistract(uint32 timer);
void MoveTaxiFlight(uint32 path, uint32 pathnode);
void MoveDistract(uint32 time);
Mangos对移动进行了单独的处理,这个是它的一个亮点和优点。
五、结论
1. 网游服务器AI的基本结构还是体现出来了,一个网游服务器AI系统确实主要是由游戏对象、AI和移动组成;
2. 关键类设计得过于复杂,需要进一步细化和模块化;像Unit和Player里面的战斗和技能很必要作为一个独立模块来设计和实现。Creature和Player等复杂的类,需要划分出状态,否则太多状态变量和条件判断,很容易出错,而且不容易修改和扩充。
3. 代码复杂度比较高,一般程序员难于驾驭;如有人员替换,维护和修改比较困难;
4. 无内存池和对象池,大量使用new和delete。长时间运行后,服务器效率是个问题;
5. 重用性很差,很难在上面搞出个其它不是“WOW”的游戏。听说国内有公司打算用Mangos搞其它网游,肯定修改不动,不了了之。
Mangos确实只是一个爱好和兴趣的产物,并不适合实际的商业网络游戏。新手学习有一定的参考,但是参考价值不大,因为门槛还是比较高的(如巨大的类、实现地图区块广播的模板技术),新手额外要花不少代价。对新手来说,我更建议看一些韩派或国内网游的实现。但是Mangos毕竟把WOW给模拟出来了,我对Mangos的开发者们的付出和工作量还是表示敬意。

[挂载人]初学MPEG

个人签名--------------------------------------------------------------------------------

Please Login (or Sign Up) to leave a comment