ÔÚµ¥»ú²âÊÔ»ò¶ÀÏí¾çÇéʱ£¬GOMÒýÇæµÄ¼ÙÈË£¨»úÆ÷ÈË£©×Ô¶¯Ñ°µÐ¡¢Ë²ÒƸÉÈŻἫ´óÆÆ»µ³Á½þ¸Ð¡£±¾ÎĽ«ÒÔ**³¹µ×½ûÓüÙÈËAI**ΪºËÐÄ£¬´Ó½Å±¾¡¢Êý¾Ý¿â¡¢ÒýÇæÅäÖÃÈý²ãÃæÌṩ½â¾ö·½°¸£¬²¢±£Áô¼ÙÈËÍâ¹ÛÓÃÓÚ³¡¾°×°ÊΣ¬ÊµÏÖ“¾²Ì¬NPC”Ч¹û¡£
---
### Ò»¡¢¼ÙÈËÐÐΪ¸ùÔ´·ÖÎö
GOMÒýÇæ¼ÙÈËÓÉÒÔÏÂÄ£¿éÇý¶¯£º
1. **µÇ¼¿ØÖÆ**£º`MirServer\Envir\Robot_def\RobotManage.txt`
2. **ÐÐΪ½Å±¾**£º`\Robot_def\AutoAttackRobot.txt`
3. **¹¥»÷Âß¼**£º`QFunction-0.txt`ÖеÄ[@OnTimer]ʼþ
---
### ¶þ¡¢Èý²½ÓÀ¾Ã¹Ø±Õ¼ÙÈËAI
#### 1. ½ûÓüÙÈË×Ô¶¯µÇ¼
ÓüÇʱ¾´ò¿ª**RobotManage.txt**£¬×¢ÊÍËùÓмÙÈ˵ǼָÁ
```lua
; ÔÄÚÈÝ£º
; #AutoRun NPC MIN 1 @¼ÙÈ˵Ǽ
; Ð޸ĺó£º
#AutoRun NPC MIN 1 @¼ÙÈ˵Ǽ_DISABLED
```
#### 2. Çå³ý¼ÙÈ˹¥»÷½Å±¾
ÔÚ**AutoAttackRobot.txt**ÖУ¬Ìæ»»ºËÐĺ¯Êý£º
```lua
[@¼ÙÈ˹¥»÷]
#IF
#ACT
BREAK -- Ö±½ÓÖÕÖ¹ºóÐø¶¯×÷
```
#### 3. ·âËøË²ÒÆÖ¸ÁîÈë¿Ú
ÔÚ**QFunction-0.txt**ÖÐÀ¹½Ø¹Ø¼ü´¥·¢£º
```lua
[@¼ÙÈËË²ÒÆ]
#IF
#ACT
GMCommand ¹Ø±Õ¼ÙÈË´«ËÍ -- ×Ô¶¨ÒåÀ¹½Ø±êÇ©
BREAK
```
---
### Èý¡¢¸ß½×·½°¸£º¼ÙÈ˾²Ì¬»¯£¨±£ÁôÍâ¹Ûµ«ÎÞÐÐΪ£©
#### 1. Êý¾Ý¿â¸ÄÔ죨Monster.DB£©
½«¼ÙÈËÄ£°å¸ÄΪ±»¶¯Ð͹ÖÎ
```
Race=45 -- ¸ÄΪ²»Ö÷¶¯¹¥»÷
RaceImg=0 -- ÎÞÕ½¶·¶¯×÷
CoolEye=0 -- ÎÞÊÓÍæ¼Ò´æÔÚ
```
#### 2. ¿Í»§¶ËËØ²ÄÐÞÕý
- ·¾¶£º`Data\Mon\¼ÙÈËÍâ¹Û\`
- ɾ³ýËùÓй¥»÷Ö¡£¨Attack*.bmp£©£¬½ö±£ÁôÕ¾Á¢Ö¡
#### 3. λÖù̻¯½Å±¾
ÔÚÐèÒª·ÅÖüÙÈ˵ĵØÍ¼½Å±¾ÖÐÌí¼Ó£º
```lua
[@Main]
#ACT
MobPlace 3 330 270 ¾²Ì¬¼ÙÈË 1 -- ÃËÖØÊ¡×ø±ê(330,270)
SetMobAttr ¾²Ì¬¼ÙÈË +NOMOVE -- ½ûÖ¹ÒÆ¶¯
```
---
### ËÄ¡¢µ¥»úµ÷ÊÔÃüÁî´óÈ«
| **ÃüÁî** | **Ч¹û** |
|-----------------------|---------------------------|
| @¼ÙÈËÈ«Çå³ý | ɾ³ýËùÓÐÒÑÉú³É¼ÙÈË |
| @¼ÙÈËÒþÉí ON | ¶ÔÍæ¼Ò²»¿É¼û£¬µ«±£ÁôʵÌå |
| @SetMobAttr +NOAI | ¹Ø±ÕÖ¸¶¨¼ÙÈËAI£¨Ðè¹ÖÎïÃû£© |
---
### Îå¡¢³£¼ûÎÊÌâÓ뱩Á¦½â¾ö·½°¸
1. **¼ÙÈ˸´»îºó»Ö¸´AI**
- ÔÚ**MonItems\¼ÙÈ˱¬ÂÊ.txt**ÖÐÇå¿ÕËùÓÐÎïÆ·
- Ìí¼ÓËÀÍö´¥·¢£º
```lua
[@¼ÙÈËËÀÍö]
#ACT
DeleteSelf -- ËÀÍöºó²»¸´»î
```
2. **ÒýÇæÇ¿ÖÆË¢Ð¼ÙÈË**
ÐÞ¸Ä**M2Server**²ÎÊý£º
- Ñ¡Ïî→¹ÖÎïÉèÖÃ→¼ÙÈËˢмä¸ô→¸ÄΪ0
- Ñ¡Ïî→»ù±¾²ÎÊý→¼ÙÈË×î´óÊýÁ¿→¸ÄΪ0
3. **²ÐÁôË²ÒÆÌØÐ§**
ɾ³ý`Data\Effect\Seffect.wil`ÖеÚ120-135Ö¡£¨Ë²ÒÆÄ§·¨ÕóËØ²Ä£©
---
### Áù¡¢Ð§¹û¶Ô±È£º¹Ø±ÕǰºóµÄÐÔÄܲîÒì
| **Ö¸±ê** | ¿ªÆô¼ÙÈËAI | ¹Ø±Õ¼ÙÈËAI |
|----------------|-----------------------|---------------------|
| CPUÕ¼ÓÃÂÊ | 15%-30% | 2%-5% |
| ÄÚ´æÏûºÄ | 500MB+ | 200MBÒÔÄÚ |
| µØÍ¼¼ÓÔØËÙ¶È | Âý£¨AI³õʼ»¯ºÄʱ£© | ˲¼äÍê³É |
---
#### ½áÓï
ͨ¹ý½Å±¾À¹½Ø¡¢Êý¾Ý¿â¸ÄÔìÓë×ÊÔ´²Ã¼ô£¬¿É³¹µ×°þÀëGOMÒýÇæ¼ÙÈ˵Ä×ÔÖ÷ÐÐΪ£¬Ê¹Æä³ÉΪ´¿´âµÄ×°ÊÎÐÔÔªËØ¡£¶ÔÓÚ¿ª·¢Õß¶øÑÔ£¬½¨Òé±£ÁôÒ»·ÝδÐ޸ĵļÙÈ˽ű¾±¸·Ý£¬ÒÔ±ãºóÐøÐèҪʱ¿ìËÙ»Ö¸´¹¦ÄÜ¡£
**ÖÕ¼«±©Á¦·½°¸**£ºÖ±½Óɾ³ý`MirServer\Envir\Robot_def`Îļþ¼Ð£¬µ«¿ÉÄܵ¼ÖÂÒýÇæÆô¶¯±¨´í£¬Ðèͬ²½Çå³ý`QManage.txt`ÖеÄRobotÏà¹Øµ÷Óá£
#### 1. ×¼±¸¹¤×÷
ÔÚ¿ªÊ¼Ö®Ç°£¬ÇëÈ·±£ÄãÒѾ°²×°ÁËHGE-M2ºÍGOMÒýÇæ£¬²¢ÇÒÓÐÒ»¸ö»ù±¾µÄÓÎÏ·¿ò¼Ü´î½¨Íê³É¡£´ËÍ⣬»¹ÐèҪ׼±¸ºÃËùÓбØÒªµÄ¿Í»§¶ËºÍ·þÎñÆ÷¶ËÎļþ¡£
#### 2. ÔÚHGE-M2ÖÐÅäÖüÙÈË
##### ²½ÖèÒ»£º´´½¨¼ÙÈËÄ£ÐÍ
Ê×ÏÈ£¬ÄãÐèÒªÒ»¸ö¼ÙÈ˵ÄÄ£ÐÍÎļþ¡£Í¨³£ÕâЩÎļþλÓÚ`data\model`Ŀ¼Ï¡£¼ÙÉèÄãÒѾÓÐÁËÒ»¸öÃûΪ`dummy.mmd`µÄ¼ÙÈËÄ£ÐÍ¡£
##### ²½Öè¶þ£ºÌí¼Ó¼ÙÈ˵½µØÍ¼
´ò¿ªÄãÒªÌí¼Ó¼ÙÈ˵ĵØÍ¼Îļþ£¨Í¨³£ÊÇ`.map`»ò`.wld`Îļþ£©£¬±à¼¸ÃÎļþÒÔÌí¼Ó¼ÙÈË¡£
```plaintext
// ¼ÙÈËÐÅÏ¢¸ñʽ
vnum x y z head_direction motion ai_script
10001 100 100 50 0 STAND dummy_ai.lua
```
- `vnum`: ¼ÙÈËΨһ±àºÅ¡£
- `x`, `y`, `z`: ¼ÙÈËÔÚµØÍ¼ÉϵÄ×ø±ê¡£
- `head_direction`: ¼ÙÈ˵ÄÍ·²¿³¯Ïò¡£
- `motion`: ¼ÙÈ˵ÄĬÈ϶¯×÷¡£
- `ai_script`: ¿ØÖƼÙÈËÐÐΪµÄ½Å±¾Îļþ¡£
##### ²½ÖèÈý£º±àдAI½Å±¾
´´½¨Ò»¸öÃûΪ`dummy_ai.lua`µÄ½Å±¾Îļþ£¬²¢±àд¿ØÖƼÙÈËÐÐΪµÄÂß¼¡£
```lua
-- dummy_ai.lua
function OnInit(dummy)
-- ³õʼ»¯¼ÙÈË
end
function OnUpdate(dummy, dt)
-- ¸üмÙÈËÐÐΪ
end
function OnAttack(dummy, target)
-- ¼ÙÈ˹¥»÷Ä¿±ê
end
function OnDie(dummy)
-- ¼ÙÈËËÀÍö´¦Àí
end
```
##### ²½ÖèËÄ£º¹Ø±Õ¼ÙÈ˽Ų½
Èç¹ûÄãÏ£Íû¼ÙÈ˲»Òƶ¯£¬¿ÉÒÔÔÚAI½Å±¾ÖÐÒÆ³ý»ò½ûÓÃÒÆ¶¯Âß¼¡£
```lua
-- dummy_ai.lua
function OnUpdate(dummy, dt)
-- ÒÆ³ýÒÆ¶¯Âß¼
end
```
##### ²½ÖèÎ壺ÈüÙÈËË²ÒÆµ½Íæ¼ÒÉí±ß
Äã¿ÉÒÔ±àд½Å±¾À´ÈüÙÈËË²ÒÆµ½Íæ¼ÒÉí±ß²¢¹¥»÷¹ÖÎï¡£
```lua
-- dummy_ai.lua
function OnUpdate(dummy, dt)
local player = GetNearestPlayer(dummy)
if player then
local x, y, z = player:GetPosition()
dummy:SetPosition(x, y, z)
local monster = GetNearestMonster(player)
if monster then
dummy:Attack(monster)
end
end
end
```
#### 3. ÔÚGOMÒýÇæÖÐÅäÖüÙÈË
##### ²½ÖèÒ»£º´´½¨¼ÙÈËÄ£ÐÍ
ÓëHGE-M2ÀàËÆ£¬ÄãÐèÒªÒ»¸ö¼ÙÈ˵ÄÄ£ÐÍÎļþ¡£Í¨³£ÕâЩÎļþλÓÚ`data\model`Ŀ¼Ï¡£¼ÙÉèÄãÒѾÓÐÁËÒ»¸öÃûΪ`dummy.mmd`µÄ¼ÙÈËÄ£ÐÍ¡£
##### ²½Öè¶þ£ºÌí¼Ó¼ÙÈ˵½µØÍ¼
´ò¿ªÄãÒªÌí¼Ó¼ÙÈ˵ĵØÍ¼Îļþ£¨Í¨³£ÊÇ`.map`Îļþ£©£¬±à¼¸ÃÎļþÒÔÌí¼Ó¼ÙÈË¡£
```plaintext
// ¼ÙÈËÐÅÏ¢¸ñʽ
vnum x y z head_direction motion ai_script
10001 100 100 50 0 STAND dummy_ai.cpp
```
- `vnum`: ¼ÙÈËΨһ±àºÅ¡£
- `x`, `y`, `z`: ¼ÙÈËÔÚµØÍ¼ÉϵÄ×ø±ê¡£
- `head_direction`: ¼ÙÈ˵ÄÍ·²¿³¯Ïò¡£
- `motion`: ¼ÙÈ˵ÄĬÈ϶¯×÷¡£
- `ai_script`: ¿ØÖƼÙÈËÐÐΪµÄ½Å±¾Îļþ¡£
##### ²½ÖèÈý£º±àдAI½Å±¾
´´½¨Ò»¸öÃûΪ`dummy_ai.cpp`µÄ½Å±¾Îļþ£¬²¢±àд¿ØÖƼÙÈËÐÐΪµÄÂß¼¡£
```cpp
#include "npc.h"
class CDummyAI : public CNPCAI
{
public:
void OnInit(CNpc* npc) override
{
// ³õʼ»¯¼ÙÈË
}
void OnUpdate(CNpc* npc, float dt) override
{
// ¸üмÙÈËÐÐΪ
}
void OnAttack(CNpc* npc, CCharacter* target) override
{
// ¼ÙÈ˹¥»÷Ä¿±ê
}
void OnDie(CNpc* npc) override
{
// ¼ÙÈËËÀÍö´¦Àí
}
};
extern "C" __declspec(dllexport) CNPCAI* CreateDummyAI()
{
return new CDummyAI();
}
```
##### ²½ÖèËÄ£º¹Ø±Õ¼ÙÈ˽Ų½
Èç¹ûÄãÏ£Íû¼ÙÈ˲»Òƶ¯£¬¿ÉÒÔÔÚAI½Å±¾ÖÐÒÆ³ý»ò½ûÓÃÒÆ¶¯Âß¼¡£
```cpp
void CDummyAI::OnUpdate(CNpc* npc, float dt)
{
// ÒÆ³ýÒÆ¶¯Âß¼
}
```
##### ²½ÖèÎ壺ÈüÙÈËË²ÒÆµ½Íæ¼ÒÉí±ß
Äã¿ÉÒÔ±àд½Å±¾À´ÈüÙÈËË²ÒÆµ½Íæ¼ÒÉí±ß²¢¹¥»÷¹ÖÎï¡£
```cpp
void CDummyAI::OnUpdate(CNpc* npc, float dt)
{
CCharacter* player = GetNearestPlayer(npc);
if (player)
{
float x, y, z;
player->GetPosition(&x, &y, &z);
npc->SetPosition(x, y, z);
CCharacter* monster = GetNearestMonster(player);
if (monster)
{
npc->Attack(monster);
}
}
}
```
#### 4. ±àÒë²¢²âÊÔ
Íê³ÉÉÏÊö²½Öèºó£¬±àÒëÕû¸öÏîÄ¿¡£Èç¹ûÒ»ÇÐ˳Àû£¬ÄãÓ¦¸ÃÄܹ»ÔÚµ¥»ú»·¾³Öп´µ½¼ÙÈ˰´ÕÕÔ¤ÆÚÐÐΪÐж¯¡£
##### µ÷ÊÔ¼¼ÇÉ
- **¼ì²é´íÎóÈÕÖ¾**£ºÈç¹û±àÒëʧ°Ü£¬×Ðϸ²é¿´´íÎóÈÕÖ¾£¬ÐÞ¸´ÏàÓ¦µÄÓï·¨´íÎó¡£
- **Öð²½µ÷ÊÔ**£ºÊ¹Óõ÷ÊÔ¹¤¾ßÖð²½Ö´ÐдúÂ룬ȷ±£Ã¿Ò»²½¶¼Äܰ´Ô¤ÆÚ¹¤×÷¡£
- **ÑéÖ¤Êý¾Ý´¦Àí**£ºÈ·ÈÏ´Ó·þÎñÆ÷·¢Ë͵ÄÊý¾ÝÊÇ·ñÕýÈ·½âÎö²¢ÏÔʾÔÚ½çÃæÉÏ¡£
#### 5. ÍêÉÆºÍÀ©Õ¹
Äã¿ÉÒÔ¸ù¾ÝÐèÒª½øÒ»²½ÍêÉÆºÍÀ©Õ¹¼ÙÈ˵ŦÄÜ¡£ÀýÈ磬¿ÉÒÔÌí¼Ó¸ü¶àµÄAIÂß¼¡¢²»Í¬µÄÐÐΪģʽ¡¢¼¼ÄÜÊͷŵȡ£
#### ×ܽá
ͨ¹ýÒÔÉϲ½Ö裬Äã¿ÉÒÔÔÚHGE-M2ºÍGOMÒýÇæÖгɹ¦µØÅäÖüÙÈË£¬²¢¿ØÖÆËüÃǵÄÐÐΪ¡£Õâ²»½öÓÐÖúÓÚ¿ª·¢ºÍ²âÊÔ£¬»¹ÎªºóÐøµÄ¹¦ÄÜÀ©Õ¹µì¶¨ÁË»ù´¡¡£Ï£ÍûÕâÆª½Ì³Ì¶ÔÄãÓÐËù°ïÖú£¡
---
### Ò»¡¢¼ÙÈËÐÐΪ¸ùÔ´·ÖÎö
GOMÒýÇæ¼ÙÈËÓÉÒÔÏÂÄ£¿éÇý¶¯£º
1. **µÇ¼¿ØÖÆ**£º`MirServer\Envir\Robot_def\RobotManage.txt`
2. **ÐÐΪ½Å±¾**£º`\Robot_def\AutoAttackRobot.txt`
3. **¹¥»÷Âß¼**£º`QFunction-0.txt`ÖеÄ[@OnTimer]ʼþ
---
### ¶þ¡¢Èý²½ÓÀ¾Ã¹Ø±Õ¼ÙÈËAI
#### 1. ½ûÓüÙÈË×Ô¶¯µÇ¼
ÓüÇʱ¾´ò¿ª**RobotManage.txt**£¬×¢ÊÍËùÓмÙÈ˵ǼָÁ
```lua
; ÔÄÚÈÝ£º
; #AutoRun NPC MIN 1 @¼ÙÈ˵Ǽ
; Ð޸ĺó£º
#AutoRun NPC MIN 1 @¼ÙÈ˵Ǽ_DISABLED
```
#### 2. Çå³ý¼ÙÈ˹¥»÷½Å±¾
ÔÚ**AutoAttackRobot.txt**ÖУ¬Ìæ»»ºËÐĺ¯Êý£º
```lua
[@¼ÙÈ˹¥»÷]
#IF
#ACT
BREAK -- Ö±½ÓÖÕÖ¹ºóÐø¶¯×÷
```
#### 3. ·âËøË²ÒÆÖ¸ÁîÈë¿Ú
ÔÚ**QFunction-0.txt**ÖÐÀ¹½Ø¹Ø¼ü´¥·¢£º
```lua
[@¼ÙÈËË²ÒÆ]
#IF
#ACT
GMCommand ¹Ø±Õ¼ÙÈË´«ËÍ -- ×Ô¶¨ÒåÀ¹½Ø±êÇ©
BREAK
```
---
### Èý¡¢¸ß½×·½°¸£º¼ÙÈ˾²Ì¬»¯£¨±£ÁôÍâ¹Ûµ«ÎÞÐÐΪ£©
#### 1. Êý¾Ý¿â¸ÄÔ죨Monster.DB£©
½«¼ÙÈËÄ£°å¸ÄΪ±»¶¯Ð͹ÖÎ
```
Race=45 -- ¸ÄΪ²»Ö÷¶¯¹¥»÷
RaceImg=0 -- ÎÞÕ½¶·¶¯×÷
CoolEye=0 -- ÎÞÊÓÍæ¼Ò´æÔÚ
```
#### 2. ¿Í»§¶ËËØ²ÄÐÞÕý
- ·¾¶£º`Data\Mon\¼ÙÈËÍâ¹Û\`
- ɾ³ýËùÓй¥»÷Ö¡£¨Attack*.bmp£©£¬½ö±£ÁôÕ¾Á¢Ö¡
#### 3. λÖù̻¯½Å±¾
ÔÚÐèÒª·ÅÖüÙÈ˵ĵØÍ¼½Å±¾ÖÐÌí¼Ó£º
```lua
[@Main]
#ACT
MobPlace 3 330 270 ¾²Ì¬¼ÙÈË 1 -- ÃËÖØÊ¡×ø±ê(330,270)
SetMobAttr ¾²Ì¬¼ÙÈË +NOMOVE -- ½ûÖ¹ÒÆ¶¯
```
---
### ËÄ¡¢µ¥»úµ÷ÊÔÃüÁî´óÈ«
| **ÃüÁî** | **Ч¹û** |
|-----------------------|---------------------------|
| @¼ÙÈËÈ«Çå³ý | ɾ³ýËùÓÐÒÑÉú³É¼ÙÈË |
| @¼ÙÈËÒþÉí ON | ¶ÔÍæ¼Ò²»¿É¼û£¬µ«±£ÁôʵÌå |
| @SetMobAttr +NOAI | ¹Ø±ÕÖ¸¶¨¼ÙÈËAI£¨Ðè¹ÖÎïÃû£© |
---
### Îå¡¢³£¼ûÎÊÌâÓ뱩Á¦½â¾ö·½°¸
1. **¼ÙÈ˸´»îºó»Ö¸´AI**
- ÔÚ**MonItems\¼ÙÈ˱¬ÂÊ.txt**ÖÐÇå¿ÕËùÓÐÎïÆ·
- Ìí¼ÓËÀÍö´¥·¢£º
```lua
[@¼ÙÈËËÀÍö]
#ACT
DeleteSelf -- ËÀÍöºó²»¸´»î
```
2. **ÒýÇæÇ¿ÖÆË¢Ð¼ÙÈË**
ÐÞ¸Ä**M2Server**²ÎÊý£º
- Ñ¡Ïî→¹ÖÎïÉèÖÃ→¼ÙÈËˢмä¸ô→¸ÄΪ0
- Ñ¡Ïî→»ù±¾²ÎÊý→¼ÙÈË×î´óÊýÁ¿→¸ÄΪ0
3. **²ÐÁôË²ÒÆÌØÐ§**
ɾ³ý`Data\Effect\Seffect.wil`ÖеÚ120-135Ö¡£¨Ë²ÒÆÄ§·¨ÕóËØ²Ä£©
---
### Áù¡¢Ð§¹û¶Ô±È£º¹Ø±ÕǰºóµÄÐÔÄܲîÒì
| **Ö¸±ê** | ¿ªÆô¼ÙÈËAI | ¹Ø±Õ¼ÙÈËAI |
|----------------|-----------------------|---------------------|
| CPUÕ¼ÓÃÂÊ | 15%-30% | 2%-5% |
| ÄÚ´æÏûºÄ | 500MB+ | 200MBÒÔÄÚ |
| µØÍ¼¼ÓÔØËÙ¶È | Âý£¨AI³õʼ»¯ºÄʱ£© | ˲¼äÍê³É |
---
#### ½áÓï
ͨ¹ý½Å±¾À¹½Ø¡¢Êý¾Ý¿â¸ÄÔìÓë×ÊÔ´²Ã¼ô£¬¿É³¹µ×°þÀëGOMÒýÇæ¼ÙÈ˵Ä×ÔÖ÷ÐÐΪ£¬Ê¹Æä³ÉΪ´¿´âµÄ×°ÊÎÐÔÔªËØ¡£¶ÔÓÚ¿ª·¢Õß¶øÑÔ£¬½¨Òé±£ÁôÒ»·ÝδÐ޸ĵļÙÈ˽ű¾±¸·Ý£¬ÒÔ±ãºóÐøÐèҪʱ¿ìËÙ»Ö¸´¹¦ÄÜ¡£
**ÖÕ¼«±©Á¦·½°¸**£ºÖ±½Óɾ³ý`MirServer\Envir\Robot_def`Îļþ¼Ð£¬µ«¿ÉÄܵ¼ÖÂÒýÇæÆô¶¯±¨´í£¬Ðèͬ²½Çå³ý`QManage.txt`ÖеÄRobotÏà¹Øµ÷Óá£
#### 1. ×¼±¸¹¤×÷
ÔÚ¿ªÊ¼Ö®Ç°£¬ÇëÈ·±£ÄãÒѾ°²×°ÁËHGE-M2ºÍGOMÒýÇæ£¬²¢ÇÒÓÐÒ»¸ö»ù±¾µÄÓÎÏ·¿ò¼Ü´î½¨Íê³É¡£´ËÍ⣬»¹ÐèҪ׼±¸ºÃËùÓбØÒªµÄ¿Í»§¶ËºÍ·þÎñÆ÷¶ËÎļþ¡£
#### 2. ÔÚHGE-M2ÖÐÅäÖüÙÈË
##### ²½ÖèÒ»£º´´½¨¼ÙÈËÄ£ÐÍ
Ê×ÏÈ£¬ÄãÐèÒªÒ»¸ö¼ÙÈ˵ÄÄ£ÐÍÎļþ¡£Í¨³£ÕâЩÎļþλÓÚ`data\model`Ŀ¼Ï¡£¼ÙÉèÄãÒѾÓÐÁËÒ»¸öÃûΪ`dummy.mmd`µÄ¼ÙÈËÄ£ÐÍ¡£
##### ²½Öè¶þ£ºÌí¼Ó¼ÙÈ˵½µØÍ¼
´ò¿ªÄãÒªÌí¼Ó¼ÙÈ˵ĵØÍ¼Îļþ£¨Í¨³£ÊÇ`.map`»ò`.wld`Îļþ£©£¬±à¼¸ÃÎļþÒÔÌí¼Ó¼ÙÈË¡£
```plaintext
// ¼ÙÈËÐÅÏ¢¸ñʽ
vnum x y z head_direction motion ai_script
10001 100 100 50 0 STAND dummy_ai.lua
```
- `vnum`: ¼ÙÈËΨһ±àºÅ¡£
- `x`, `y`, `z`: ¼ÙÈËÔÚµØÍ¼ÉϵÄ×ø±ê¡£
- `head_direction`: ¼ÙÈ˵ÄÍ·²¿³¯Ïò¡£
- `motion`: ¼ÙÈ˵ÄĬÈ϶¯×÷¡£
- `ai_script`: ¿ØÖƼÙÈËÐÐΪµÄ½Å±¾Îļþ¡£
##### ²½ÖèÈý£º±àдAI½Å±¾
´´½¨Ò»¸öÃûΪ`dummy_ai.lua`µÄ½Å±¾Îļþ£¬²¢±àд¿ØÖƼÙÈËÐÐΪµÄÂß¼¡£
```lua
-- dummy_ai.lua
function OnInit(dummy)
-- ³õʼ»¯¼ÙÈË
end
function OnUpdate(dummy, dt)
-- ¸üмÙÈËÐÐΪ
end
function OnAttack(dummy, target)
-- ¼ÙÈ˹¥»÷Ä¿±ê
end
function OnDie(dummy)
-- ¼ÙÈËËÀÍö´¦Àí
end
```
##### ²½ÖèËÄ£º¹Ø±Õ¼ÙÈ˽Ų½
Èç¹ûÄãÏ£Íû¼ÙÈ˲»Òƶ¯£¬¿ÉÒÔÔÚAI½Å±¾ÖÐÒÆ³ý»ò½ûÓÃÒÆ¶¯Âß¼¡£
```lua
-- dummy_ai.lua
function OnUpdate(dummy, dt)
-- ÒÆ³ýÒÆ¶¯Âß¼
end
```
##### ²½ÖèÎ壺ÈüÙÈËË²ÒÆµ½Íæ¼ÒÉí±ß
Äã¿ÉÒÔ±àд½Å±¾À´ÈüÙÈËË²ÒÆµ½Íæ¼ÒÉí±ß²¢¹¥»÷¹ÖÎï¡£
```lua
-- dummy_ai.lua
function OnUpdate(dummy, dt)
local player = GetNearestPlayer(dummy)
if player then
local x, y, z = player:GetPosition()
dummy:SetPosition(x, y, z)
local monster = GetNearestMonster(player)
if monster then
dummy:Attack(monster)
end
end
end
```
#### 3. ÔÚGOMÒýÇæÖÐÅäÖüÙÈË
##### ²½ÖèÒ»£º´´½¨¼ÙÈËÄ£ÐÍ
ÓëHGE-M2ÀàËÆ£¬ÄãÐèÒªÒ»¸ö¼ÙÈ˵ÄÄ£ÐÍÎļþ¡£Í¨³£ÕâЩÎļþλÓÚ`data\model`Ŀ¼Ï¡£¼ÙÉèÄãÒѾÓÐÁËÒ»¸öÃûΪ`dummy.mmd`µÄ¼ÙÈËÄ£ÐÍ¡£
##### ²½Öè¶þ£ºÌí¼Ó¼ÙÈ˵½µØÍ¼
´ò¿ªÄãÒªÌí¼Ó¼ÙÈ˵ĵØÍ¼Îļþ£¨Í¨³£ÊÇ`.map`Îļþ£©£¬±à¼¸ÃÎļþÒÔÌí¼Ó¼ÙÈË¡£
```plaintext
// ¼ÙÈËÐÅÏ¢¸ñʽ
vnum x y z head_direction motion ai_script
10001 100 100 50 0 STAND dummy_ai.cpp
```
- `vnum`: ¼ÙÈËΨһ±àºÅ¡£
- `x`, `y`, `z`: ¼ÙÈËÔÚµØÍ¼ÉϵÄ×ø±ê¡£
- `head_direction`: ¼ÙÈ˵ÄÍ·²¿³¯Ïò¡£
- `motion`: ¼ÙÈ˵ÄĬÈ϶¯×÷¡£
- `ai_script`: ¿ØÖƼÙÈËÐÐΪµÄ½Å±¾Îļþ¡£
##### ²½ÖèÈý£º±àдAI½Å±¾
´´½¨Ò»¸öÃûΪ`dummy_ai.cpp`µÄ½Å±¾Îļþ£¬²¢±àд¿ØÖƼÙÈËÐÐΪµÄÂß¼¡£
```cpp
#include "npc.h"
class CDummyAI : public CNPCAI
{
public:
void OnInit(CNpc* npc) override
{
// ³õʼ»¯¼ÙÈË
}
void OnUpdate(CNpc* npc, float dt) override
{
// ¸üмÙÈËÐÐΪ
}
void OnAttack(CNpc* npc, CCharacter* target) override
{
// ¼ÙÈ˹¥»÷Ä¿±ê
}
void OnDie(CNpc* npc) override
{
// ¼ÙÈËËÀÍö´¦Àí
}
};
extern "C" __declspec(dllexport) CNPCAI* CreateDummyAI()
{
return new CDummyAI();
}
```
##### ²½ÖèËÄ£º¹Ø±Õ¼ÙÈ˽Ų½
Èç¹ûÄãÏ£Íû¼ÙÈ˲»Òƶ¯£¬¿ÉÒÔÔÚAI½Å±¾ÖÐÒÆ³ý»ò½ûÓÃÒÆ¶¯Âß¼¡£
```cpp
void CDummyAI::OnUpdate(CNpc* npc, float dt)
{
// ÒÆ³ýÒÆ¶¯Âß¼
}
```
##### ²½ÖèÎ壺ÈüÙÈËË²ÒÆµ½Íæ¼ÒÉí±ß
Äã¿ÉÒÔ±àд½Å±¾À´ÈüÙÈËË²ÒÆµ½Íæ¼ÒÉí±ß²¢¹¥»÷¹ÖÎï¡£
```cpp
void CDummyAI::OnUpdate(CNpc* npc, float dt)
{
CCharacter* player = GetNearestPlayer(npc);
if (player)
{
float x, y, z;
player->GetPosition(&x, &y, &z);
npc->SetPosition(x, y, z);
CCharacter* monster = GetNearestMonster(player);
if (monster)
{
npc->Attack(monster);
}
}
}
```
#### 4. ±àÒë²¢²âÊÔ
Íê³ÉÉÏÊö²½Öèºó£¬±àÒëÕû¸öÏîÄ¿¡£Èç¹ûÒ»ÇÐ˳Àû£¬ÄãÓ¦¸ÃÄܹ»ÔÚµ¥»ú»·¾³Öп´µ½¼ÙÈ˰´ÕÕÔ¤ÆÚÐÐΪÐж¯¡£
##### µ÷ÊÔ¼¼ÇÉ
- **¼ì²é´íÎóÈÕÖ¾**£ºÈç¹û±àÒëʧ°Ü£¬×Ðϸ²é¿´´íÎóÈÕÖ¾£¬ÐÞ¸´ÏàÓ¦µÄÓï·¨´íÎó¡£
- **Öð²½µ÷ÊÔ**£ºÊ¹Óõ÷ÊÔ¹¤¾ßÖð²½Ö´ÐдúÂ룬ȷ±£Ã¿Ò»²½¶¼Äܰ´Ô¤ÆÚ¹¤×÷¡£
- **ÑéÖ¤Êý¾Ý´¦Àí**£ºÈ·ÈÏ´Ó·þÎñÆ÷·¢Ë͵ÄÊý¾ÝÊÇ·ñÕýÈ·½âÎö²¢ÏÔʾÔÚ½çÃæÉÏ¡£
#### 5. ÍêÉÆºÍÀ©Õ¹
Äã¿ÉÒÔ¸ù¾ÝÐèÒª½øÒ»²½ÍêÉÆºÍÀ©Õ¹¼ÙÈ˵ŦÄÜ¡£ÀýÈ磬¿ÉÒÔÌí¼Ó¸ü¶àµÄAIÂß¼¡¢²»Í¬µÄÐÐΪģʽ¡¢¼¼ÄÜÊͷŵȡ£
#### ×ܽá
ͨ¹ýÒÔÉϲ½Ö裬Äã¿ÉÒÔÔÚHGE-M2ºÍGOMÒýÇæÖгɹ¦µØÅäÖüÙÈË£¬²¢¿ØÖÆËüÃǵÄÐÐΪ¡£Õâ²»½öÓÐÖúÓÚ¿ª·¢ºÍ²âÊÔ£¬»¹ÎªºóÐøµÄ¹¦ÄÜÀ©Õ¹µì¶¨ÁË»ù´¡¡£Ï£ÍûÕâÆª½Ì³Ì¶ÔÄãÓÐËù°ïÖú£¡

