이동하는 몹

2007.04.12 13:07

그리움 조회 수:283 추천:58

자료출처 : GAME BBS (Telnet gamebbs.co.kr)

/***************************************************************/
/* 이동몹 소스.. */
/***************************************************************/

/*
  이 소스에 관한 권리는 저 '암흑마객'에게 있구요.
  무한대전 소스를 이용해서 머드를 운영하는 모든 무료 머드에서
  자유롭게 이용하실 수 있습니다.

  만약 다른 곳에 올리시려면 이 설명글을 빼지마시고 전부 올려
  주십시오.

  소스에 관한 의문점은 'www2.nais.co.kr 7528' [마계지문] 으로 오셔서
  문의하십시오.
*/

// ^^ 다시 쓰기 귀찮아서, 저번에 룸 에딧 소스 올릴때의 글을 베껴썼음^^

int crt_move(creature* crt_ptr)
{
       xtag* xp;
       int found = 0;
       exit_* list[4];
       long i;
       room* rom_ptr;
       room* old_rom;
       creature* temp_crt;

       old_rom = crt_ptr->parent_rom;
       xp = crt_ptr->parent_rom->first_ext;
   while( xp )
       {
       if( !F_ISSET(xp->ext, XNOSEE) && !F_ISSET(xp->ext, XNOSEE) &&
                       !F_ISSET(xp->ext, XCLOSD) && !F_ISSET(xp->ext, XINVIS) &
&
                       !F_ISSET(xp->ext, XLOCKD) && !F_ISSET(xp->ext, XSECRT) )
               {
                       if( !strcmp(xp->ext->name, "동") || !strcmp(xp->ext->nam
e, "서") ||
                               !strcmp(xp->ext->name, "남") || !strcmp(xp->ext-
>name, "북") )
                               list[ found++ ] = xp->ext;
               }

               xp = xp->next_tag;
   }

       if( crt_ptr->first_enm || !found ) return(0);

       crt_ptr->lasttime[LT_MWAND].ltime = time(0);
       i = rand()%found;

   if( load_rom(list[i]->room, &rom_ptr) < 0 || rom_ptr == old_rom ) return(0
);


       broadcast_rom(-1, old_rom->rom_num,
               "\n%1M%j %s쪽으로 갔습니다.", crt_ptr, "1", list[i]->name);

       del_crt_rom(crt_ptr, old_rom);
       add_crt_rom(crt_ptr, rom_ptr, 1);
       add_active(crt_ptr);

       return(1);
}

위의 함수를 전역 처리해 주시던가, update_active() 함수위에 적어 주세요.

그런 후에, 다음은 update_active() 함수의 시작 일부분 입니다.

       last_active_update = t;
   if( !(cp = first_active) ) return;

       while( cp )
       {
       if( !cp ) break;

               crt_ptr = cp->crt;
       rom_ptr = crt_ptr->parent_rom;

               if( !rom_ptr->first_ply )
               {
                       del_active(crt_ptr);
                       cp = first_active;
                       continue;
               }



update.c의 update_active()함수에서 위의 부분을 찾으세요.

그런후 아래와 같이 고치시길 바랍니다.

       last_active_update = t;
   if( !(cp = first_active) ) return;

       while( cp )
       {
       if( !cp ) break;

               crt_ptr = cp->crt;
       rom_ptr = crt_ptr->parent_rom;

               if( F_ISSET(crt_ptr, MYMOVE) && !crt_ptr->first_enm )
               {
                       if( t-crt_ptr->lasttime[LT_MWAND].ltime >
               crt_ptr->proficiency[1] && crt_move(crt_ptr) )
           {
                               cp = first_active;
                               continue;
                       }
               }

               if( !F_ISSET(crt_ptr, MYMOVE) && !rom_ptr->first_ply )
               {
                       del_active(crt_ptr);
                       cp = first_active;
                       continue;
               }

그리고 또 한가지 고치실 곳이 있습니다.
room.c의 add_permcrt_rom() 함수에 보시면, 다음과 같은 부분이 있습니다.

for(j = 0; j < n-m; j++)
{
       l = load_crt(rom_ptr->perm_mon[i].misc, &crt_ptr);
       if(l < 0) continue;

       /* ...생략.. */

       if(!F_ISSET(crt_ptr, MNRGLD) && crt_ptr->gold)
               crt_ptr->gold = mrand(crt_ptr->gold/10, crt_ptr->gold);
       F_SET(crt_ptr, MPERMT);
       add_crt_rom(crt_ptr, rom_ptr);
       if( rom_ptr->first_ply )
               add_active(crt_ptr);
}

이 부분을 아래와 같이 고치세요.

for(j = 0; j < n-m; j++)
{
       l = load_crt(rom_ptr->perm_mon[i].misc, &crt_ptr);
       if(l < 0) continue;

       /* ....생략... */

       if(!F_ISSET(crt_ptr, MNRGLD) && crt_ptr->gold)
               crt_ptr->gold = mrand(crt_ptr->gold/10, crt_ptr->gold);

       F_SET(crt_ptr, MPERMT);
       add_crt_rom(crt_ptr, rom_ptr);
       if( rom_ptr->first_ply )
               add_active(crt_ptr);

       /* 아래 다섯줄 추가 */
       if( F_ISSET(crt_ptr, MYMOVE) )
       {
               rom_ptr->perm_mon[i].ltime = t;
               if( !rom_ptr->first_ply )
                       add_active(crt_ptr);
       }
}

^^..정말 간단하죠^^

이제 마지막으로 고치실곳..


room.c의 del_ply_rom() 함수를 찾으세요.

함수내용 중에 다음과 같은 부분이 있습니다.

if( !temp )
{
       cp = rom_ptr->first_mon;

       while( cp ) {
               del_active(cp->crt);
               cp = cp->next_tag;
       }
}

위의 부분을 아래와 같이 고치세요.

if( !temp )
{
       cp = rom_ptr->first_mon;

       while( cp ) {
               if( !F_ISSET(cp->crt, MYMOVE) )
                       del_active(cp->crt);
               cp = cp->next_tag;
       }
}

그럼..끝^^

일단 몬스터 flag중 남는 곳에 MYMOVE란 flag를 추가하시구요,

몹의 crt_ptr->proficiency[1]가 바로 이동하는 시간이 됩니다.
이곳에 넣은 초만큼 이동하죠, 30을 넣으면 30초에 한번씩 이동..^^

무한에선 이동몹이라는 개념이 없고, 또 존단위 리젠이 아닌, 몹 단위
리젠이라 그게 사실 좀 불가능 하기도 합니다.

하지만, 이리 저리 머드하러 떠돌아 다니다 보니 이동하는 몹들이 부러버서
그냥 한번 만들어 봤습니다.

보시면 아시겠지만, del_ply_rom()이나 add_permcrt_rom()함수 등에서
player가 없을 경우 active 된 몹리스트에서 제외 시키는 부분을 막은 거구요,
add_permcrt_rom() 함수는 죽은 시간으로 시작하는게 아니고 생성된 시간을
last time으로 정한거죵...당연히^^

그리고 active_update()함수 역시 player가 없을 경우 이동몹은 리스트에서
제외시키는 것을 막고, 또 시간을 검색해서 몹을 이동시키는..매우 간단한
추가를 한 겁니다. 하지만 이동이라는 것은 아주 잘 되죵^^

하지만, 만들어 놓고 보니 문제가 좀 있네요.

그건 다름이 아닌 존단위 리젠이 아닌, 몹 단위 리젠때문 입니다.
몹 단위로 리젠을 시키기 때문에, 몹이 이동했을 경우 다시 그 몹의 생성 시간이
지나면, 몹이 있던 없던 간에 다시 생성 된다는 점 입니다.

아마 무한에서 이 기능이 빠진 이유도 바로 이 이유때문인지도 모르겠네요.

이를 해결하기 위한 초보적 방법으론 변수 두개정도를 creature 구조체에 추가하면
그럭저럭 해결할 수 있는 방법이 있습니다.
쩝..전 그냥 마을에 돌아 다니며 대화하는 주민 몇마리 만들어 놓으려고 굳이
변수 소모해가면서 추가하지는 않았습니다. 하시고 싶으신 분은 해보세요.

쿠..역쉬 무한의 한계 때문인지 영 만족스럽지 않네요.

구럼...www2.nais.co.kr 7528 <-- 마계지문 임다..많이들 오세용^^

홈지기 "그륨"


XE Login