µ±Ç°Î»Öà : 145zÓÎÏ·Õ¾¡¡|¡¡ÈÈѪ´«Ææ¡¡|¡¡¼¼Êõ½Ì³Ì¡¡|¡¡

GOM´«ÆæÒýÇæÈ«ÆÁÎü¹ÖÖÕ¼«½Ì³Ì£¬´Ó¼¼Äܽű¾µ½·¶Î§¿ØÖƵÄÍêÕû·½°¸

Èȶȣº
È«ÆÁÎü¹ÖÊÇ´«Ææ±ä̬°æ±¾Öеľ­µä¹¦ÄÜ£¬µ«Ô­ÉúGOMÒýÇæ²¢Î´Ö±½ÓÖ§³Ö¡£±¾ÎĽ«Í¨¹ý**¼¼ÄÜ´¥·¢+×ø±ê±éÀúËã·¨**ʵÏÖÖÇÄÜÎü¹Ö£¬º­¸ÇÎÞCDģʽ¡¢·¶Î§µ÷½Ú¡¢BOSSÃâÒߵȸ߼¶¹¦ÄÜ£¬²¢ÌṩÅäÌ׵ķÀ¿¨Î»¡¢·À±ÀÀ£ÓÅ»¯²ßÂÔ¡£

---

### Ò»¡¢»ù´¡Îü¹Ö½Å±¾ÊµÏÖ
#### 1. Êý¾Ý¿â¼¼ÄÜÅäÖã¨Magic.DB£©

| ×Ö¶ÎÃû | Öµ | ˵Ã÷ |
|--------------|-----------------|----------------------|
| Name | È«ÆÁÎü¹Ö | ¼¼ÄÜÏÔʾÃû³Æ |
| EffectType | 42 | ×Ô¶¨Òå¼¼ÄÜ´¥·¢±êʶ |
| NeedL1 | 100 | ¼¼Äܵȼ¶ÐèÇó |
| Delay | 5000 | Àäȴʱ¼ä£¨ºÁÃ룩 |


#### 2. QFunction-0.txt´¥·¢Âß¼­
```lua
[@MagSelfFunc42] -- ¶ÔÓ¦EffectType=42
#IF
CHECKGAMEGOLD > 99 -- ¼ì²âÔª±¦
CHECKRANGEMONCOUNT <$X> <$Y> 50 > 0 -- 50¸ñÄÚ´æÔÚ¹ÖÎï
#ACT
GAMEGOLD - 100
CALCVAR HUMAN Îü¹Ö´ÎÊý + 1
SAVEVAR HUMAN Îü¹Ö´ÎÊý ..\QuestDiary\Îü¹Öͳ¼Æ.txt
MOV A50 <$X>
MOV A51 <$Y>
GOTO @Îü¹ÖÖ÷Ñ­»·

[@Îü¹ÖÖ÷Ñ­»·]
#ACT
GetRangeMonster <$STR(A50)> <$STR(A51)> 50 0 0
WHILE <$STR(S$¹ÖÎïÃû³Æ)> != ""
; ÒÆ¶¯¹ÖÎïµ½Íæ¼Ò×ø±ê
MonsterMove <$STR(S$¹ÖÎïÃû³Æ)> <$X> <$Y>
; ·ÀÖ¹BOSS±»Îü
IF NOT CHECKMONNAMELIST ..\QuestDiary\Îü¹ÖºÚÃûµ¥.txt
PlayEffect <$STR(S$¹ÖÎïÃû³Æ)> 5 -- Îü¸½ÌØÐ§
ENDIF
GetRangeMonster <$STR(A50)> <$STR(A51)> 50 0 0
ENDWHILE
SENDMSG 6 ³É¹¦Îü¸½<$OUTPUT(<$HUMAN(Îü¹Ö´ÎÊý)>)>Ö»¹ÖÎ
BREAK
```



---

### ¶þ¡¢¸ß¼¶¹¦ÄÜÍØÕ¹
#### 1. ·¶Î§µ÷½Ú²ÎÊý»¯
```lua
; ¶ÁÈ¡ÅäÖÃÎļþ
GETVALUELINE ..\QuestDiary\Îü¹ÖÅäÖÃ.txt 1 S$Îü¹Ö°ë¾¶
CHECKRANGEMONCOUNT <$X> <$Y> <$STR(S$Îü¹Ö°ë¾¶)> > 0
```



#### 2. BOSSÃâÒß»úÖÆ
ÔÚ**Îü¹ÖºÚÃûµ¥.txt**ÖÐÌí¼ÓBOSSÃû³Æ£º
```
°µÖ®Ä§Áú½ÌÖ÷
»ðÁúÉñ
```


#### 3. ³ðºÞ×ªÒÆ·À¿¨Î»
```lua
MonsterMove <$STR(S$¹ÖÎïÃû³Æ)> <$X> <$Y>
ChangeTarget <$STR(S$¹ÖÎïÃû³Æ)> <$USERNAME> -- Ç¿ÖÆ¹¥»÷ÊÍ·ÅÕß
```



---

### Èý¡¢·À±ÀÀ£ÓëÐÔÄÜÓÅ»¯
#### 1. ¹ÖÎïÊýÁ¿·ÖÒ³´¦Àí
```lua
MOV N$µ±Ç°Ò³Êý 0
WHILE <$STR(S$¹ÖÎïÃû³Æ)> != "" && <$STR(N$µ±Ç°Ò³Êý)> < 20
...
INC N$µ±Ç°Ò³Êý 1
DELAY 100 -- ÿ100ms´¦Àí1Ö»
ENDWHILE
```



#### 2. ÄÚ´æÊÍ·ÅÇ¿ÖÆ»ØÊÕ
```lua
CLEARMAPMON <$MAP> -- Çå³ý·Ç»îÔ¾¹ÖÎï
RECLAIM -- ÄÚ´æ»ØÊÕ
```



#### 3. Ò쳣״̬¼ì²â
```lua
#IF
CHECKSTATUS 10 -- ¼ì²âÍæ¼ÒÊÇ·ñ´¦ÓÚÂé±Ô״̬
#ACT
BREAK
```



---

### ËÄ¡¢¿ÉÊÓ»¯ÅäÖò˵¥
ÔÚ**QManage.txt**Öд´½¨¹ÜÀí½çÃæ£º
```lua
[@Îü¹ÖÉèÖÃ]
#ACT
OPENMERCHANTBIG Îü¹ÖÅäÖÃ 0 0 0
; ½çÃæ°´Å¥
[@µ÷Õû°ë¾¶]
#ACT
MOV D$Îü¹Ö°ë¾¶ <$INPUT(ÇëÊäÈëÎü¹Ö°ë¾¶(1-100):)>
```



---

### Î塢Ч¹û¶Ô±ÈÓë²ÎÊý½¨Òé

| **²ÎÊýÏî** | µÍÅä·þÍÆ¼öÖµ | ¸ßÅä·þÍÆ¼öÖµ |
|------------------|------------------|------------------|
| µ¥´Î×î´óÎü¹ÖÊý | 20 | 50 |
| Îü¹Ö°ë¾¶ | 30 | 70 |
| Àäȴʱ¼ä | 10000ms | 5000ms |
| ÑÓ³Ù¼ä¸ô | 200ms/Ö» | 100ms/Ö» |


---

#### ½áÓï
ͨ¹ý·ÖÒ³´¦Àí¡¢ÄÚ´æ»ØÊÕÓëÒì³£¼ì²â£¬¿ÉÔÚGOMÒýÇæÖÐÎȶ¨ÔËÐÐÈ«ÆÁÎü¹Ö¹¦ÄÜ¡£¹Ø¼üµãÔÚÓÚ£º
1. **·ÖÖ¡Ö´ÐÐ**£º±ÜÃâµ¥´ÎÑ­»·´¦Àí¹ý¶à¹ÖÎï
2. **ºÚÃûµ¥»úÖÆ**£º±£»¤ºËÐÄBOSS²»±»ÆÆ»µÌôÕ½ÐÔ
3. **×ÊÔ´ÊÍ·Å**£º¶¨ÆÚCLEARMAPMON·ÀÖ¹ÄÚ´æÐ¹Â©

¸½Ôù¹¤¾ß°ü£º
- Îü¹Ö·¶Î§¿ÉÊÓ»¯µ÷ÊÔ²å¼þ
- ¹ÖÎïÒÆ¶¯¹ì¼£¼Ç¼Æ÷
- Îü¹Ö¼¼ÄÜÌØÐ§ËØ²Ä°ü

ÕÆÎÕÉÏÊö·½°¸ºó£¬¿É½øÒ»²½¿ª·¢“ÖÇÄܾ۹֔£¨ÓÅÏÈÎü¸½¸ß±¬ÂʹÖÎ»ò“·´ÏòÕð·É”µÈÑÜÉú¹¦ÄÜ£¬·á¸»ÓÎÏ·Íæ·¨¡£

#### 1. ×¼±¸¹¤×÷
ÔÚ¿ªÊ¼Ö®Ç°£¬ÇëÈ·±£ÄãÒѾ­°²×°ÁËGOMÒýÇæ£¬²¢ÇÒÓÐÒ»¸ö»ù±¾µÄÓÎÏ·¿ò¼Ü´î½¨Íê³É¡£´ËÍ⣬»¹ÐèҪ׼±¸ºÃËùÓбØÒªµÄ¿Í»§¶ËºÍ·þÎñÆ÷¶ËÎļþ¡£

#### 2. Àí½âÈ«ÆÁÎü¹ÖÂß¼­

##### È«ÆÁÎü¹ÖµÄ»ù±¾Ô­Àí
È«ÆÁÎü¹ÖµÄºËÐÄÔÚÓÚÈùÖÎï×Ô¶¯Òƶ¯µ½Íæ¼ÒÉí±ß¡£¾ßÌå²½ÖèÈçÏ£º
1. **¼ì²âÖÜΧµÄËùÓйÖÎï**£º±éÀúµ±Ç°µØÍ¼ÉϵÄËùÓйÖÎï¡£
2. **¼ÆËã¾àÀë**£º¼ÆËãÿ¸ö¹ÖÎïÓëÍæ¼ÒÖ®¼äµÄ¾àÀë¡£
3. **ÒÆ¶¯¹ÖÎï**£ºÈç¹û¹ÖÎïÔÚÒ»¶¨·¶Î§ÄÚ£¬½«ÆäÒÆ¶¯µ½Íæ¼ÒÉí±ß¡£

#### 3. ʵÏÖÈ«ÆÁÎü¹Ö¹¦ÄÜ

##### ²½ÖèÒ»£ºÌí¼Ó¼¼ÄÜÅäÖÃ
Ê×ÏÈ£¬ÔÚ`data\skill_proto.txt`ÎļþÖÐÌí¼ÓÒ»¸öеļ¼ÄÜÀ´±íʾȫÆÁÎü¹Ö¡£

```plaintext
vnum name type level skill_point target_type weapon_sub_type damage_factor range delay cast_time effect_duration effect_value script
10003 È«ÆÁÎü¹Ö SKILL_TYPE_MAGIC 50 50 TARGET_AREA WEAPON_SUBTYPE_NONE 0.0 500 2000 3000 EF_PULL_MONSTERS 0
```

- `vnum`: ¼¼ÄÜΨһ±àºÅ¡£
- `name`: ¼¼ÄÜÃû³Æ¡£
- `type`: ¼¼ÄÜÀàÐÍ£¨Ä§·¨£©¡£
- `level`: ¼¼ÄÜËùÐèµÈ¼¶¡£
- `skill_point`: ¼¼ÄܵãÊýÏûºÄ¡£
- `target_type`: Ä¿±êÀàÐÍ£¨ÇøÓòÄ¿±ê£©¡£
- `weapon_sub_type`: ÎäÆ÷×ÓÀàÐÍ£¨Í¨³£ÎªNONE£©¡£
- `damage_factor`: ËðÉËÒò×Ó£¨¶ÔÓÚÎü¹Ö¼¼ÄÜΪ0£©¡£
- `range`: Ê©·¨·¶Î§¡£
- `delay`: Àäȴʱ¼ä¡£
- `cast_time`: Ê©·¨Ê±¼ä¡£
- `effect_duration`: Ч¹û³ÖÐøÊ±¼ä¡£
- `effect_value`: Ч¹ûÖµ£¨¶ÔÓÚÎü¹Ö¼¼ÄÜΪ0£©¡£
- `script`: ½Å±¾£¨Èç¹ûÐèÒª¶îÍâÂß¼­£©¡£

##### ²½Öè¶þ£º´¦Àí¼¼ÄÜЧ¹û
´ò¿ª`src\skill_manager.cpp`Îļþ£¬ÕÒµ½´¦Àí¼¼ÄÜЧ¹ûµÄ²¿·Ö£¬Ìí¼ÓÈ«ÆÁÎü¹ÖµÄЧ¹û¡£

```cpp
void CSkillManager::ApplySkillEffect(CCharacter* caster, CCharacter* target, SKILL_INFO* skillInfo)
{
switch (skillInfo->vnum)
{
case 10003: // È«ÆÁÎü¹Ö
PullMonsters(caster, skillInfo);
break;
// ÆäËû¼¼ÄÜ...
}
}

void CSkillManager::PullMonsters(CCharacter* caster, SKILL_INFO* skillInfo)
{
float range = skillInfo->range;
Vector3f casterPos = caster->GetPosition();

for (auto& obj : GetWorld()->GetObjects())
{
if (obj->GetType() == OBJECT_TYPE_MONSTER)
{
CMonster* monster = dynamic_cast<CMonster*>(obj);
if (monster && !monster->IsDead())
{
Vector3f monsterPos = monster->GetPosition();
float distance = CalculateDistance(casterPos, monsterPos);

if (distance <= range)
{
MoveMonsterToPlayer(monster, caster);
}
}
}
}
}

float CalculateDistance(Vector3f pos1, Vector3f pos2)
{
return sqrt(pow(pos2.x - pos1.x, 2) + pow(pos2.y - pos1.y, 2) + pow(pos2.z - pos1.z, 2));
}

void MoveMonsterToPlayer(CMonster* monster, CCharacter* player)
{
Vector3f playerPos = player->GetPosition();
Vector3f direction = playerPos - monster->GetPosition();
Normalize(direction);

// ÒÆ¶¯¹ÖÎïµ½Íæ¼ÒλÖÃ
monster->SetPosition(playerPos.x, playerPos.y, playerPos.z);
}
```

##### ²½ÖèÈý£ºÌí¼Ó¼¼Äܵ½½ÇÉ«
ÔÚ`data\char_proto.txt`ÎļþÖУ¬¸ø½ÇÉ«Ìí¼ÓÈ«ÆÁÎü¹Ö¼¼ÄÜ¡£

```plaintext
vnum class race gender str dex int con hit point attack_defense damage resist_magic magic_defense poison_resist hp_recovery sp_recovery special_effect skills
1 WARRIOR HUMAN MALE 20 20 10 15 100 100 10 10 0 0 0 0 0 10003
```

- `skills`: ½ÇɫӵÓеļ¼ÄÜÁÐ±í£¬ÓöººÅ·Ö¸ô¡£

#### 4. ±àÒë²¢²âÊÔ

##### ²½ÖèÒ»£º±àÒëÏîÄ¿
È·±£ËùÓÐÐ޸ĺóµÄ´úÂë¶¼Äܳɹ¦±àÒë¡£

```sh
g++ -o server src/server_main.cpp src/monster.cpp src/skill_manager.cpp -lengine
```

##### ²½Öè¶þ£ºÆô¶¯ÓÎÏ·
Æô¶¯·þÎñÆ÷ºÍ¿Í»§¶Ë£¬¹Û²ìÈ«ÆÁÎü¹Ö¼¼ÄÜÊÇ·ñÕý³£¹¤×÷¡£

##### µ÷ÊÔ¼¼ÇÉ
- **¼ì²é´íÎóÈÕÖ¾**£ºÈç¹û±àÒëʧ°Ü£¬×Ðϸ²é¿´´íÎóÈÕÖ¾£¬ÐÞ¸´ÏàÓ¦µÄÓï·¨´íÎó¡£
- **Öð²½µ÷ÊÔ**£ºÊ¹Óõ÷ÊÔ¹¤¾ßÖð²½Ö´ÐдúÂ룬ȷ±£Ã¿Ò»²½¶¼Äܰ´Ô¤ÆÚ¹¤×÷¡£
- **ÑéÖ¤Êý¾Ý´¦Àí**£ºÈ·ÈÏ´Ó·þÎñÆ÷·¢Ë͵ÄÊý¾ÝÊÇ·ñÕýÈ·½âÎö²¢ÏÔʾÔÚ½çÃæÉÏ¡£

#### 5. ÍêÉÆºÍÀ©Õ¹

##### Ôö¼ÓÀäȴʱ¼ä
ΪÁË·ÀÖ¹ÀÄÓÃÈ«ÆÁÎü¹Ö¼¼ÄÜ£¬¿ÉÒÔÔö¼ÓÀäȴʱ¼ä¡£

```plaintext
vnum name type level skill_point target_type weapon_sub_type damage_factor range delay cast_time effect_duration effect_value script
10003 È«ÆÁÎü¹Ö SKILL_TYPE_MAGIC 50 50 TARGET_AREA WEAPON_SUBTYPE_NONE 0.0 500 2000 3000 EF_PULL_MONSTERS 0
```

##### Ìí¼ÓÌØÐ§
¿ÉÒÔÔÚÊ©·Å¼¼ÄÜʱÌí¼ÓÌØÐ§£¬ÔöÇ¿ÊÓ¾õЧ¹û¡£

```cpp
void CSkillManager::PullMonsters(CCharacter* caster, SKILL_INFO* skillInfo)
{
float range = skillInfo->range;
Vector3f casterPos = caster->GetPosition();

// Ìí¼ÓÊ©·¨ÌØÐ§
AddSpellEffect(caster, SPELL_EFFECT_PULL_MONSTERS);

for (auto& obj : GetWorld()->GetObjects())
{
if (obj->GetType() == OBJECT_TYPE_MONSTER)
{
CMonster* monster = dynamic_cast<CMonster*>(obj);
if (monster && !monster->IsDead())
{
Vector3f monsterPos = monster->GetPosition();
float distance = CalculateDistance(casterPos, monsterPos);

if (distance <= range)
{
MoveMonsterToPlayer(monster, caster);
}
}
}
}
}

void AddSpellEffect(CCharacter* caster, int effectId)
{
// Ìí¼ÓÌØÐ§Âß¼­
caster->AddEffect(effectId);
}
```

##### ¸Ä½øÒƶ¯Âß¼­
ΪÁ˱ÜÃâ¹ÖÎï˲¼ä´«Ë͵½Íæ¼ÒÉí±ß£¬¿ÉÒԸĽøÒƶ¯Âß¼­£¬Ê¹Æäƽ»¬Òƶ¯¡£

```cpp
void MoveMonsterToPlayer(CMonster* monster, CCharacter* player)
{
Vector3f playerPos = player->GetPosition();
Vector3f direction = playerPos - monster->GetPosition();
Normalize(direction);

// ƽ»¬Òƶ¯¹ÖÎïµ½Íæ¼ÒλÖÃ
float moveSpeed = 5.0f; // ÒÆ¶¯ËÙ¶È
Vector3f newPosition = monster->GetPosition() + direction * moveSpeed;
monster->SetPosition(newPosition.x, newPosition.y, newPosition.z);

// ¼ì²éÊÇ·ñµ½´ïÄ¿µÄµØ
float distance = CalculateDistance(newPosition, playerPos);
if (distance < 1.0f) // ÅжÏÊÇ·ñµ½´ïÄ¿µÄµØ
{
monster->SetPosition(playerPos.x, playerPos.y, playerPos.z);
}
}
```

#### 6. ±àÒë²¢ÔٴβâÊÔ

##### ²½ÖèÒ»£º±àÒëÏîÄ¿
È·±£ËùÓÐÐ޸ĺóµÄ´úÂë¶¼Äܳɹ¦±àÒë¡£

```sh
g++ -o server src/server_main.cpp src/monster.cpp src/skill_manager.cpp -lengine
```

##### ²½Öè¶þ£ºÆô¶¯ÓÎÏ·
Æô¶¯·þÎñÆ÷ºÍ¿Í»§¶Ë£¬¹Û²ìÈ«ÆÁÎü¹Ö¼¼ÄÜÊÇ·ñÕý³£¹¤×÷£¬²¢ÇÒÐÂÔöµÄ¹¦ÄÜÊÇ·ñÉúЧ¡£

#### ×ܽá
ͨ¹ýÒÔÉϲ½Ö裬Äã¿ÉÒÔÔÚGOMÒýÇæÖгɹ¦µØÊµÏÖÈ«ÆÁÎü¹Ö¹¦ÄÜ¡£Õâ²»½öÌáÉýÁËÓÎÏ·µÄ»¥¶¯ÐÔºÍÌôÕ½ÐÔ£¬»¹ÄÜÌṩ¸üºÃµÄÓÎÏ·ÌåÑ顣ϣÍûÕâÆª½Ì³Ì¶ÔÄãÓÐËù°ïÖú£¡