示例#1
0
CNPC *CCenario::removeNPC(int idNPC)
{
	CNPC *temp = (CNPC*)_jogadores->removePersonagem(idNPC);
	_contador->removeID(temp->getSceneID());
	return(temp);
	//return((CNPC*)_npcs->removePersonagem(idNPC));
}
示例#2
0
bool CNPC::PlanTalking(void)
{
	int i,j,x,wants = 0;
	CNPC* npc = NULL;
	//gather all NPCs in current view
	for (i = 0; i < WRLD_CHR_VIEW; i++)
		for (j = 0; j < WRLD_CHR_VIEW; j++) {
			if (view[i][j].npc) {
				x = GetWantTalkTo(view[i][j].npc);
				if (x > wants) {
					npc = view[i][j].npc;
					wants = x;
				}
			}
		}
	if ((!npc) || (wants < 1)) return false;
	//if NPC is just right here, start talking
	if (distance(my_coord,npc->GetCrd()) < 1.5f)
		return StartTalking(npc);
	else {
		//set aim one cell near NPC
//		my_stats.aim = getnextpoint(npc->GetCrd(),my_coord,NULL);
//		my_stats.aimed = true;
		my_state = AimTo(getnextpoint(npc->GetCrd(),my_coord,NULL))? NPC_Running:NPC_Browsing;
	}
	return true;
}
示例#3
0
文件: zone.cpp 项目: kerlw/Dawn
void CZone::removeNPC( CNPC *npcToDelete )
{
		for ( size_t curNPCNr=0; curNPCNr<npcs.size(); ++curNPCNr ) {
			CNPC *curNPC = npcs[ curNPCNr ];
			if ( curNPC == npcToDelete ) {
				curNPC->markAsDeleted();
				break;
			}
		}
}
示例#4
0
文件: zone.cpp 项目: kerlw/Dawn
void CZone::cleanupNPCList()
{
	size_t curNPCNr = 0;
	while ( curNPCNr < npcs.size() ) {
		CNPC *curNPC = npcs[ curNPCNr ];
		if ( curNPC->isMarkedAsDeletable() ) {
			npcs.erase( npcs.begin() + curNPCNr );
			// TODO: delete curNPC. There seem to be some problems at the moment.
			//delete curNPC;
		} else {
			++curNPCNr;
		}
	}
}
示例#5
0
文件: magic.cpp 项目: kerlw/Dawn
void CMagic::process()
{
  int a = 0;

  std::vector<CNPC*> zoneNPCs = Globals::getCurrentZone()->getNPCs();
  for (unsigned int x=0; x<zoneNPCs.size(); x++)
  {
    //zoneNPCs[x].
    CNPC *curNPC = zoneNPCs[x];

    // is the npc colliding with the spell and make sure it's alive
    if( collision(curNPC) && curNPC->isAlive() )
    {
      // loop through the active spells on the npc if it has any and make sure the effect isn't cast twice
      std::vector<std::pair<CSpellActionBase*, uint32_t> > activeSpells = curNPC->getActiveSpells();
      if( activeSpells.size() > 0 )
      {
        for ( size_t curSpell = 0; curSpell < activeSpells.size(); curSpell++ )
        {
          // there is no active spell matching this one, cast it
          if( activeSpells[curSpell].first->getID() == spell->getID() )
          {
            a++;
          }
        }

        if( a == 0 )
        {
          CSpellActionBase *s = spell->cast( creator, curNPC, true );
          s->startEffect();
          curNPC->addActiveSpell( s );
        }
      }
      else // cast the spell
      {
        CSpellActionBase *s = spell->cast( creator, curNPC, true );
        s->startEffect();
        curNPC->addActiveSpell( s );
      }
    }
  }
}
示例#6
0
文件: zone.cpp 项目: kerlw/Dawn
std::string CZone::getLuaSaveText() const
{
  std::ostringstream oss;
  oss << "DawnInterface.setCurrentZone( \"" << zoneName << "\" );" << std::endl;

  /* Save call indirections (must be added before spawnpoints since used there). */
  oss << "-- event handlers" << std::endl;
  for ( size_t curEventHandlerNr=0; curEventHandlerNr<eventHandlers.size(); ++curEventHandlerNr )
  {
    CallIndirection* curEventHandler = eventHandlers[ curEventHandlerNr ];
    std::string eventHandlerSaveText = curEventHandler->getLuaSaveText();
    oss << eventHandlerSaveText;
  }

  /* Save all spawnpoints. */
  oss << "-- spawnpoints" << std::endl;
  for ( size_t curNpcNr=0; curNpcNr < npcs.size(); ++curNpcNr )
  {
    CNPC *curNPC = npcs[ curNpcNr ];
    /* Save current NPC. */
    std::string npcSaveText = curNPC->getLuaSaveText();
    oss << npcSaveText;
  }

  /* Save shop data (this ought to be put into the shop somehow as soon as shops are customizable). */
  oss << "-- shops" << std::endl;
  oss << "local curShop = DawnInterface.addShop();" << std::endl;
  oss << "curShop:clear();" << std::endl;
  for ( size_t curTab=0; curTab<3; ++curTab )
  {
    for ( size_t curItemNr=0; curItemNr < shopWindow->shopkeeperInventory[curTab].size(); ++curItemNr )
    {
      oss << "curShop:addItem( itemDatabase[\""
          << shopWindow->shopkeeperInventory[curTab][curItemNr]->getItem()->getID()
          << "\"] );"
          << std::endl;
    }
  }

  /* Save interaction points. */
  oss << "-- interaction points" << std::endl;
  for ( size_t curInteractionNr=0; curInteractionNr < interactionPoints.size(); ++curInteractionNr )
  {
    InteractionPoint *curInteractionPoint = interactionPoints[ curInteractionNr ];
    std::string interactionSaveText = curInteractionPoint->getLuaSaveText();
    oss << interactionSaveText;
  }

  /* Save interaction regions. */
  oss << "-- interaction regions" << std::endl;
  for ( size_t curInteractionNr=0; curInteractionNr < interactionRegions.size(); ++curInteractionNr )
  {
    InteractionRegion *curInteractionRegion = interactionRegions[ curInteractionNr ];
    std::string interactionSaveText = curInteractionRegion->getLuaSaveText();
    oss << interactionSaveText;
  }

  /* Save ground loot. */
  oss << "-- ground loot" << std::endl;
  for ( size_t curGroundItemNr=0; curGroundItemNr < groundLoot.groundItems.size(); ++curGroundItemNr )
  {
    sGroundItems curGroundItem = groundLoot.groundItems[ curGroundItemNr ];
    Item* item = curGroundItem.item;
    if ( dynamic_cast<GoldHeap*>( item ) != NULL )
    {
      GoldHeap* goldHeap = dynamic_cast<GoldHeap*>( item );
      oss << "DawnInterface.restoreGroundGold( "
	  << goldHeap->numCoins() << ", "
	  << curGroundItem.xpos << ", "
	  << curGroundItem.ypos << " );" << std::endl;
    }
    else
    {
      oss << "DawnInterface.restoreGroundLootItem( "
	  << "itemDatabase[ \"" << item->getID() << "\" ], "
	  << curGroundItem.xpos << ", "
	  << curGroundItem.ypos << " );" << std::endl;
    }
  }

  return oss.str();
}
示例#7
0
void ProcDead(CPC* df, CCharacter* of)
{
    CDratanCastle * pCastle = CDratanCastle::CreateInstance();
    if (df != NULL)
    {
        pCastle->CheckRespond(df);
    }

    const char* strOFType = "UNKNOWN";
    const char* strOFName = "UNKNOWN";
    int strOFIndex = 0;

    CPC*		opc				= NULL;
    CNPC*		onpc			= NULL;
    CPet*		opet			= NULL;
    CElemental*	oelemental		= NULL;
    CAPet*		oapet			= NULL;

    if( IS_NPC(of) && TO_NPC(of)->Check_MobFlag(STATE_MONSTER_MERCENARY) && TO_NPC(of)->GetOwner() )
    {
        TO_NPC(of)->GetOwner()->SetSummonOwners_target(NULL);
    }

    switch (of->m_type)
    {
    case MSG_CHAR_PC:
        opc = TO_PC(of);
        strOFType = "PC";
        strOFName = opc->GetName();
        strOFIndex = opc->m_index;
        break;

    case MSG_CHAR_NPC:
        onpc = TO_NPC(of);
        strOFType = "NPC";
        strOFName = onpc->m_name;
        strOFIndex = onpc->m_idNum;
        break;

    case MSG_CHAR_PET:
        opet = TO_PET(of);
        opc = opet->GetOwner();
        if (opc == NULL)
            return ;
        strOFType = "PET";
        strOFName = opc->GetName();
        strOFIndex = opc->m_index;
        break;

    case MSG_CHAR_ELEMENTAL:
        oelemental = TO_ELEMENTAL(of);
        opc = oelemental->GetOwner();
        if (opc == NULL)
            return ;
        strOFType = "ELEMENTAL";
        strOFName = opc->GetName();
        strOFIndex = opc->m_index;
        break;
    case MSG_CHAR_APET:
        oapet = TO_APET(of);
        opc = oapet->GetOwner();
        if (opc == NULL)
            return ;
        strOFType = "APET";
        strOFName = opc->GetName();
        strOFIndex = opc->m_index;
        break;

    default:
        return ;
    }

    if( opc )
        opc->SetSummonOwners_target(NULL);

    // NPC에 의한 사망시 사망 패널티는 기본으로 true, PC에게 사망시 사망 패널티는 기본으로 false
    // * bPKPenalty변수는 pk 패널티를 주는것 뿐만 아니라 성향회복에도 관계되므로 성향 회복이나 패널티등 어느것에라도 걸리면 true

    bool bPvP = (opc) ? true : false;
    bool bPKPenalty = (opc) ? IsPK(opc, df) : false;
    bool bDeadPenalty = (bPvP) ? false : true;
    // 아래 boolean변수는 선언과 값대입이 따로 이루어져야 합니다.
    // bool bRestorePKOfDefensePC = true; 이런식으로 선언을 하면 UPDATE1106에서는 사용하지 않는 변수로 warning을 출력합니다.

    //소환NPC에게 죽었을 경우 처리 (EX 트랩) - 트랩의 경우에 타겟을 NPC로 사용하고 있음...ㅡㅡ;;
    if(IS_NPC(of))
    {
        CNPC* npc = TO_NPC(of);
        if(npc->m_owner > 0)
        {
            bPvP = false;
            bPKPenalty = true;
            bDeadPenalty = false;
        }
    }

    bool bRestorePKOfDefensePC;
    bRestorePKOfDefensePC = true;

    // 변신 해제
    if (df->IsSetPlayerState(PLAYER_STATE_CHANGE))
        df->CancelChange();

    if (opc)
    {
#ifdef FREE_PK_SYSTEM
        if( !gserver->m_bFreePk )
        {
#endif // FREE_PK_SYSTEM

#ifdef MAL_DISABLE_PKPENALTY
            if( gserver->m_bDisablePKPaenalty )
                bDeadPenalty = true;
            else if( !gserver->m_bDisablePKPaenalty )
            {
#endif // MAL_DISABLE_PKPENALTY
                // df가 pk모드 이거나 카오면 둘다 트루
                if (df->IsSetPlayerState(PLAYER_STATE_PKMODE) || df->IsChaotic())
                    bDeadPenalty = true;
#ifdef MAL_DISABLE_PKPENALTY
            }
#endif // MAL_DISABLE_PKPENALTY

#ifdef FREE_PK_SYSTEM
        }
#endif // FREE_PK_SYSTEM

        // 길드전
        if (opc->m_guildInfo && (opc->m_guildInfo->guild()->battleState() == GUILD_BATTLE_STATE_ING) &&
                df->m_guildInfo && (df->m_guildInfo->guild()->battleState() == GUILD_BATTLE_STATE_ING))
        {
            if (opc->m_guildInfo->guild()->battleIndex() == df->m_guildInfo->guild()->index() &&
                    df->m_guildInfo->guild()->battleIndex() == opc->m_guildInfo->guild()->index())
            {
                bDeadPenalty = false;

                int killCount = opc->m_guildInfo->guild()->killCount();

                killCount++;

                if (gserver->isRunHelper())
                {
                    CNetMsg::SP rmsg(new CNetMsg);
                    HelperGuildBattleKillReqMsg(rmsg, opc->m_guildInfo->guild()->index(), df->m_guildInfo->guild()->index());
                    SEND_Q(rmsg, gserver->m_helper);
                }
                else
                {
                    GAMELOG << init("GUILD_BATTLE")
                            << "if( gserver->isRunHelper() ) false" << delim
                            << end;
                    CNetMsg::SP rmsg(new CNetMsg);
                    GuildErrorMsg(rmsg, MSG_GUILD_ERROR_GAMESERVER);
                    SEND_Q(rmsg, opc->m_desc);
                }
            }
        }
    } // 공격자가 PC 또는 PC의 소유물일때

    // 공성 포인트 계산
    if (opc)
        CalcWarPoint(opc, df);
    else
        CalcWarPoint(of, df);

    // 공성 도중 사망은 패널티 없음
    CWarCastle* castle = CWarCastle::GetCastleObject(df->m_pZone->m_index);
#ifdef CHECK_CASTLE_AREA
    if (castle && castle->GetState() != WCSF_NORMAL && (df->GetMapAttr() & MATT_WAR || df->m_pZone->IsWarZone((int)df->m_pos.m_x, (int)df->m_pos.m_z)))
#else
    if (castle && castle->GetState() != WCSF_NORMAL && df->GetMapAttr() & MATT_WAR)
#endif // CHECK_CASTLE_AREA
    {
        DropWarCastleTokenDeadPC(df);
        bDeadPenalty = false;
    }

    /////////////////////////////////////////////
    // BANGWALL : 2005-07-18 오전 11:27:24
    // Comment : freepkzone 패널티 없음
    // 공격자와 방어자가 모두 freepkzone에 있으면 pkpenalty 없음
    if( of->GetMapAttr() == df->GetMapAttr() && of->GetMapAttr() & MATT_FREEPKZONE)
        bDeadPenalty = false;

    // PvP에서 PK 적용
    if (opc && bPvP && bPKPenalty)
        CalcPKPoint(opc, df, false);

    bool bDeadExpPenalty = true;

#ifdef FREE_PK_SYSTEM
    if( gserver->m_bFreePk )
    {
        if(!bDeadPenalty)
            bDeadExpPenalty = false;
    }
#endif // FREE_PK_SYSTEM

#if defined(LC_BILA)
    if (bPvP)
#ifdef MAL_DISABLE_PKPENALTY
        if( gserver->m_bDisablePKPaenalty )
        {
            bDeadExpPenalty = false;
        }
#endif // MAL_DISABLE_PKPENALTY
#endif

    // 퍼스널 던전은 무조건 패널티 없음
    if (df->m_pZone->IsPersonalDungeon())
        bDeadPenalty = false;

    // 경험치 하락
    LONGLONG nLoseExp = 0;
    LONGLONG nLoseSP = 0;

    // 하락된 경험치는 최근 것만 기억
    df->m_loseexp = 0;
    df->m_losesp = 0;

    if( df->m_skillPoint < 0 )
        df->m_skillPoint = 0;

    //수비자가 무소속인 경우만 사망 페널티 적용
    if (df->m_pZone->isRVRZone())
    {
        if(df->getSyndicateType() == 0)
            bDeadPenalty = true;
        else
            bDeadPenalty = false;
    }

    if (bDeadPenalty)
    {
        if (bDeadExpPenalty)
        {
            // 사망시 패널티
            if (df->m_level < 11)
            {
                /*				nLoseExp = (LONGLONG)(GetLevelupExp(df->m_level) * DEATH_PENALTY_EXP_1);
                				nLoseSP = (LONGLONG)(df->m_skillPoint * DEATH_PENALTY_SP_1);*/
                nLoseExp = 0;
                nLoseSP = 0;
            }
            else if (df->m_level < 21)
            {
                /* 5% */
                /*				nLoseExp = (LONGLONG)(GetLevelupExp(df->m_level) * DEATH_PENALTY_EXP_2);
                				nLoseSP = (LONGLONG)(df->m_skillPoint * DEATH_PENALTY_SP_2);*/
                nLoseExp = (LONGLONG)((GetLevelupExp(df->m_level) / 100) * 5);
                nLoseSP = (LONGLONG)((df->m_skillPoint / 100) * 5);
            }
            else if (df->m_level < 36)
            {
                /*				nLoseExp = (LONGLONG)(GetLevelupExp(df->m_level) * DEATH_PENALTY_EXP_3);
                				nLoseSP = (LONGLONG)(df->m_skillPoint * DEATH_PENALTY_SP_3);*/
                nLoseExp = (LONGLONG)((GetLevelupExp(df->m_level) / 100) * 3);
                nLoseSP = (LONGLONG)((df->m_skillPoint / 100) * 3);
            }
            else
            {
                /*				nLoseExp = (LONGLONG)(GetLevelupExp(df->m_level) * DEATH_PENALTY_EXP_4);
                				nLoseSP = (LONGLONG)(df->m_skillPoint * DEATH_PENALTY_SP_4);*/
                nLoseExp = (LONGLONG)((GetLevelupExp(df->m_level) / 100) * 2);
                nLoseSP = (LONGLONG)((df->m_skillPoint / 100) * 2);
            }

            // 경험의 결정 시리즈 적용
            switch (df->m_assist.m_avAddition.hcDeathExpPlus)
            {
            case 1:
            {
                nLoseExp -= 50000;
                if(nLoseExp < 0)
                    nLoseExp = 0;
            }
            break;
            case 2:
            {
                nLoseExp -= 600000;
                if(nLoseExp < 0)
                    nLoseExp = 0;
            }
            break;
            case 3:
            {
                nLoseExp /= 2;
            }
            break;
            default:
                break;
            }

            // 노력의 결정 적용
            if (df->m_assist.m_avAddition.hcDeathSPPlus)
                nLoseSP /= 2;
        }

#ifdef FREE_PK_SYSTEM
        if( !gserver->m_bFreePk )
        {
#endif // FREE_PK_SYSTEM

#ifdef MAL_DISABLE_PKPENALTY
            if( !gserver->m_bDisablePKPaenalty )
            {
#endif // MAL_DISABLE_PKPENALTY
                if (df->IsChaotic())
                {
#ifndef REFORM_PK_PENALTY_201108 // PK 패널티 리폼 :: 장비 잠금 상태 기능 삭제
// TODO : DELETE			bSaveLose = false;
                    bool bseal = false;

                    if (df->m_pkPenalty <= -130)
                    {
                        nLoseExp = nLoseExp * 225 / 100;
                        bseal = (GetRandom(1, 100) <= 13) ? true : false;
                    }
                    else if (df->m_pkPenalty <= -100)
                    {
                        nLoseExp = nLoseExp * 200 / 100;
                        bseal = (GetRandom(1, 100) <= 11) ? true : false;
                    }
                    else if (df->m_pkPenalty <=  -70)
                    {
                        nLoseExp = nLoseExp * 175 / 100;
                        bseal = (GetRandom(1, 100) <=  9) ? true : false;
                    }
                    else if (df->m_pkPenalty <=  -40)
                    {
                        nLoseExp = nLoseExp * 150 / 100;
                        bseal = (GetRandom(1, 100) <=  7) ? true : false;
                    }
                    else if (df->m_pkPenalty <=  -10)
                    {
                        nLoseExp = nLoseExp * 125 / 100;
                        bseal = (GetRandom(1, 100) <=  5) ? true : false;
                    }

                    if (bseal)
                    {
                        CItem* table[MAX_WEARING];
                        memset(table, 0, sizeof(CItem*) * MAX_WEARING);
                        int i = 0, j = 0;
                        while (i < MAX_WEARING)
                        {
                            if (df->m_wearInventory.wearItemInfo[i] && !(df->m_wearInventory.wearItemInfo[i]->getFlag() & FLAG_ITEM_SEALED))
                            {
                                // 장비에 따라 봉인 되는지 결정
                                switch (i)
                                {
                                case WEARING_HELMET:
                                case WEARING_ARMOR_UP:
                                case WEARING_WEAPON:
                                case WEARING_ARMOR_DOWN:
                                case WEARING_SHIELD:
                                case WEARING_GLOVE:
                                case WEARING_BOOTS:
                                    if(!(df->m_wearInventory.wearItemInfo[i]->m_itemProto->getItemFlag() & ITEM_FLAG_COSTUME2))
                                        table[j] = df->m_wearInventory.wearItemInfo[i];
                                    j++;
                                    break;

                                default:
                                    break;
                                }
                            }
                            i++;
                        }
                        if (j)
                        {
                            i = GetRandom(0, j - 1);

                            if (table[i])
                            {
                                table[i]->setFlag(table[i]->getFlag() | FLAG_ITEM_SEALED);

                                {
                                    CNetMsg::SP rmsg(new CNetMsg);
                                    UpdateClient::makeUpdateItemFlag(rmsg, table[i]->tab(), table[i]->getInvenIndex(), table[i]->getFlag());
                                    SEND_Q(rmsg, df->m_desc);
                                }

                                {
                                    CNetMsg::SP rmsg(new CNetMsg);
                                    PKItemSealMsg(rmsg, table[i]);
                                    SEND_Q(rmsg, df->m_desc);
                                }

                                GAMELOG << init("ITEM SEAL" , df)
                                        << "ITEM" << delim
                                        << itemlog(table[i])
                                        << end;
                            }
                        }
                    }
#endif // REFORM_PK_PENALTY_201108 // PK 패널티 리폼 :: 장비 잠금 상태 기능 삭제
                    if (nLoseExp < 0)
                        nLoseExp = 0;
                    if (nLoseSP < 0)
                        nLoseSP = 0;

                    // 060318 : bs : 공방 모두 카오PC PvP 시에는 죽은 사람 회복 없음
                    //             : 죽은카오가 선공이면 회복 없음
                    // 성향 회복

#ifndef REFORM_PK_PENALTY_201108 // PK 패널티 리폼 :: 카오 사망시 성향 회복 없음
                    if (bRestorePKOfDefensePC)
                    {
                        if( !gserver->m_bNonPK )
                            df->m_pkPenalty += 5;

                        if (df->m_pkPenalty > 0)
                            df->m_pkPenalty = 0;
                    }

                    {
                        // 페널티 수치 변경 알리기
                        CNetMsg::SP rmsg(new CNetMsg);
                        CharStatusMsg(rmsg, df, 0);
                        df->m_pArea->SendToCell(rmsg, df, false);
                    }

                    df->m_bChangeStatus = true;
                    df->CalcStatus(true);

#endif // REFORM_PK_PENALTY_201108 // PK 패널티 리폼 :: 카오 사망시 성향 회복 없음
                }
                else
                {
                    if (df->m_exp < nLoseExp)
                        nLoseExp = df->m_exp;
                }
#ifdef MAL_DISABLE_PKPENALTY
            }
            else
            {
                if( df->m_exp < nLoseExp )
                    nLoseExp = df->m_exp;
            }
#endif
#ifdef FREE_PK_SYSTEM
        }
        else
        {
            if( df->m_exp < nLoseExp )
                nLoseExp = df->m_exp;
        }
#endif // FREE_PK_SYSTEM


        if (bDeadExpPenalty)
        {
            if (nLoseExp < 0)
                nLoseExp = 0;
            if (nLoseSP < 0)
                nLoseSP = 0;
            if (df->m_skillPoint < nLoseSP)
                nLoseSP = df->m_skillPoint;
// 경험치 - 방지
            if ( df->m_exp < nLoseExp )
                nLoseExp = df->m_exp;

// 수정
            if(df->m_pZone->IsComboZone())
            {
                nLoseExp = nLoseExp / 10;
                nLoseSP = nLoseSP / 10;
            }
            df->m_exp -= nLoseExp;
            if (df->m_exp < 0)
                df->m_exp = 0;

            df->m_skillPoint -= nLoseSP;
            if (df->m_skillPoint < 0)
                df->m_skillPoint = 0;

            df->m_bChangeStatus = true;

// TODO : DELETE			if (bSaveLose)
// TODO : DELETE			{
            df->m_loseexp = nLoseExp;
            df->m_losesp = nLoseSP;
// TODO : DELETE			}
        }

        // Fixed death by npc dropping item
        if(IS_PC(of)) {
            CItem* pItem = gserver->m_itemProtoList.CreateItem(PVP_TOKEN_ID, -1, 0, 0, 1);
            if (pItem) {
                CNetMsg::SP rmsg(new CNetMsg);
                pItem->m_preferenceIndex = of->m_index;
                df->m_pArea->DropItem(pItem, df);
                ItemDropMsg(rmsg, df, pItem);
                pItem->m_pArea->SendToCell(rmsg, df, true);
            }
        }
    } // 사망 패널티 적용

    // Accessory 내구도
    int i;
    for (i = WEARING_ACCESSORY1; i <= WEARING_ACCESSORY3; i++)
    {
        if (!df->m_wearInventory.wearItemInfo[i] || df->m_wearInventory.wearItemInfo[i]->m_itemProto->getItemMaxUse() == -1)
            continue;

        df->m_wearInventory.wearItemInfo[i]->setUsed(df->m_wearInventory.wearItemInfo[i]->getUsed() - ACCESSORY_USED_DEATH);

        // 악세사리 소멸
        if (df->m_wearInventory.wearItemInfo[i]->getUsed() <= 0)
        {
            df->m_wearInventory.wearItemInfo[i]->setUsed(0);
            df->CalcStatus(true);
        }
    }

    // 보조효과 리셋
    df->m_assist.ClearAssist(true, false, true, true, false);

    // 워프중이면 취소
    if (df->IsSetPlayerState(PLAYER_STATE_WARP))
    {
        df->m_reqWarpTime = 0;
        df->m_reqWarpType = -1;
        df->m_reqWarpData = -1;

        df->m_reqWarpTime_skill = -1;
        df->m_reqWarpType_skill = -1;
        df->m_reqWarpData_skill = -1;
    }

    df->ResetPlayerState(PLAYER_STATE_SITDOWN | PLAYER_STATE_MOVING | PLAYER_STATE_WARP | PLAYER_STATE_PKMODE | PLAYER_STATE_DARKNESS);

    CPet* pet = df->GetPet();
    if (pet)
    {
        if (pet->IsMountType())
        {
            if(df->m_pZone != NULL && df->m_pZone->m_bCanMountPet == true)
            {
                // 사망 설정
                pet->SetRemainRebirthTime();
            }
        }

        {
            // 펫 상태 보냄
            CNetMsg::SP rmsg(new CNetMsg);
            ExPetStatusMsg(rmsg, pet);
            SEND_Q(rmsg, df->m_desc);
        }
    }

#ifdef LC_USA
    CAPet* apet = df->GetAPet();
    if(apet)
    {
        {
            // 펫 상태 보냄
            CNetMsg::SP rmsg(new CNetMsg);
            ExAPetStatusMsg(rmsg, apet);
            SEND_Q(rmsg, df->m_desc);
        }
    }
#endif // LC_USA

    // 소환 취소
    while (df->m_elementalList)
        df->UnsummonElemental(df->m_elementalList);
    // 강신 취소
    if (df->m_evocationIndex != EVOCATION_NONE)
        df->Unevocation();
    // 강신 시간 초기화
    df->m_pulseEvocation[0] = 0;
    df->m_pulseEvocation[1] = 0;

#ifdef GER_LOG
    GAMELOGGEM << init( 0, "CHAR_DEATH")
               << LOG_VAL("account-id", df->m_desc->m_idname ) << blank
               << LOG_VAL("character-id", df->m_desc->m_pChar->m_name ) << blank
               << LOG_VAL("zone-id", df->m_desc->m_pChar->m_pZone->m_index ) << blank
               << LOG_VAL("from-id", strOFType ) << blank
               << LOG_VAL("opponent-id", strOFIndex ) << blank
               << LOG_VAL("longitude", GET_X(df) ) << blank
               << LOG_VAL("latitude", GET_Z(df) ) << blank
               << endGer;

    if ( IS_PC(of) )
    {
        CPC *user = TO_PC(of);
        GAMELOGGEM << init( 0, "CHAR_VICTORY")
                   << LOG_VAL("account-id", user->m_desc->m_idname ) << blank
                   << LOG_VAL("character-id", user->m_desc->m_pChar->m_name ) << blank
                   << LOG_VAL("zone-id", user->m_desc->m_pChar->m_pZone->m_index ) << blank
                   /*<< LOG_VAL("from-id", strOFType ) << blank*/
                   << LOG_VAL("opponent-id", df->m_desc->m_idname ) << blank
                   << LOG_VAL("longitude", GET_X(user) ) << blank
                   << LOG_VAL("latitude", GET_Z(user) ) << blank
                   << endGer;
    }
#endif // GER_LOG
    // 로그
    GAMELOG << init("CHAR_DEATH", df)
            << "BY" << delim
            << strOFType << delim
            << strOFName << delim
            << strOFIndex << delim
            << "LOSE EXP" << delim
            << nLoseExp << delim
            << "CUR EXP" << delim
            << df->m_exp << delim
            << "LOSE SP" << delim
            << nLoseSP << delim
            << "CUR SP" << delim
            << df->m_skillPoint
            << "POS_X" << delim
            << GET_X(df) << delim
            << "POS_Z" << delim
            << GET_Z(df) << delim
            << "YLAYER" << delim
            << GET_YLAYER(df) << delim
            << "HEIGHT" << delim
            << GET_H(df)
            << end;

    DelAttackList(df);

    // 정당방위 해제
    DelRaList(df);

    if (pCastle != NULL)
    {
        if (df->GetJoinFlag(ZONE_DRATAN) != WCJF_NONE
                && pCastle->GetState() != WCSF_NORMAL
                && (df->GetMapAttr() & MATT_WAR || df->m_pZone->IsWarZone((int)df->m_pos.m_x, (int)df->m_pos.m_z) ) )
        {
            // 공성중에 공성참가
            int wait_time = -1;
            switch(df->GetJoinFlag(ZONE_DRATAN))
            {
            case WCJF_ATTACK_GUILD:
                // 부활진기가 있으면 부활대기 시간 20초, 없으면 60초
                wait_time = 60;
                if (df->m_guildInfo != NULL
                        && df->m_guildInfo->guild() != NULL)
                {
                    for(int i=0; i<7; i++)
                    {
                        if (df->m_guildInfo->guild()->index() == pCastle->m_nRebrithGuild[i])
                        {
                            wait_time = 20;
                            break;
                        }
                    }
                }
                break;
            case WCJF_OWNER:
            case WCJF_DEFENSE_GUILD:
                //  부활대기 시간 60초 - 워프타워개수*10
                int count = 0;
                for(int i=0; i<5; i++)
                {
                    if(pCastle->m_pWarpNPC[i] != NULL
                            && DEAD(pCastle->m_pWarpNPC[i]) == false)
                    {
                        count++;
                    }
                }

                wait_time = 60 - count*10;
                break;
            }

            if (wait_time > 0)
            {
                CNetMsg::SP rmsg(new CNetMsg);
                WaitTimeMsg(rmsg, wait_time);
                SEND_Q(rmsg, df->m_desc);
            }
        }
    }

#ifdef EXTREME_CUBE
    if(gserver->m_extremeCube.IsGuildCubeTime())
    {
        if(df->m_guildInfo && df->m_guildInfo->guild())
        {
            if(df->m_pZone != NULL && df->m_guildInfo->guild()->m_cubeUniqueIdx >= 0 && df->m_pZone->IsExtremeCube())
            {
                CCubeMemList* memlist = gserver->m_extremeCube.FindMemList(df->m_guildInfo->guild()->m_cubeUniqueIdx);
                if(memlist)
                {
                    memlist->DelPC(df);

                    if(opc && opc->m_guildInfo && opc->m_guildInfo->guild())
                    {
                        CCubeMemList* opcMemList = gserver->m_extremeCube.FindMemList(opc->m_guildInfo->guild());
                        if(opcMemList)
                        {
                            time_t lastCubePoint;
                            int point;
                            time(&lastCubePoint);

                            {
                                CNetMsg::SP rmsg(new CNetMsg);
                                HelperAddCubePointMsg(rmsg, opc->m_guildInfo->guild()->index(), df->m_level * 10, lastCubePoint);
                                SEND_Q(rmsg, gserver->m_helper);
                            }

                            {
                                // 개인 큐브포인트 획득
                                point = opcMemList->GetPersonalCubePoint(opc, df->m_level);
                                CNetMsg::SP rmsg(new CNetMsg);
                                HelperAddCubePointPersonalMsg(rmsg, opc->m_index, point, lastCubePoint);
                                SEND_Q(rmsg, gserver->m_helper);
                            }
                        }
                    }
                }
            }
        }
    }
    else
    {
        if(df->m_party)
        {
            if(df->m_pZone != NULL && df->m_party->m_cubeUniqueIdx >= 0 && df->m_pZone->IsExtremeCube())
            {
                CCubeMemList* memlist = gserver->m_extremeCube.FindMemList(df->m_party->m_cubeUniqueIdx);
                if(memlist)
                {
                    memlist->DelPC(df);
                    // 개인 큐브포인트 획득
                    if(opc && opc->m_party)
                    {
                        CCubeMemList* opcMemList = gserver->m_extremeCube.FindMemList(opc->m_party);
                        if(opcMemList)
                        {
                            int point;
                            time_t lastCubePoint;

                            time(&lastCubePoint);
                            point = opcMemList->GetPersonalCubePoint(opc, df->m_level);
                            CNetMsg::SP rmsg(new CNetMsg);
                            HelperAddCubePointPersonalMsg(rmsg, opc->m_index, point, lastCubePoint);
                            SEND_Q(rmsg, gserver->m_helper);
                        }
                    }
                }
            }
        }
    }
#endif // EXTREME_CUBE

    if(df && df->m_pZone->IsWarGroundZone())
    {
        if(!opc && onpc)
        {
            if(onpc->Check_MobFlag(STATE_MONSTER_TRAP) || onpc->Check_MobFlag(STATE_MONSTER_PARASITE))
            {
                opc = onpc->GetOwner();
            }
        }
        if(opc)
            GAMELOG << init("ROYAL RUMBLE DEAD PC", df) << "ATTACKER" << delim << opc->m_nick << delim << opc->m_index << end;
        CWaitPlayer* p = NULL;
        p = gserver->m_RoyalRumble.m_WaitPlayerList.GetNode(df->m_index);
        if(p)
        {
            int leveltype = p->GetLevelType();
            int leftcount = 0;

            CWaitPlayer* player = NULL;
            CWaitPlayer* playern = NULL;
            playern = gserver->m_RoyalRumble.m_WaitPlayerList.GetHead();
            while((player = playern))
            {
                playern = playern->GetNext();
                if( player->GetLevelType() == leveltype &&
                        player->GetCheckIn() == true )
                    leftcount++;
            }
            leftcount -= 2;

            {
                CNetMsg::SP rmsg(new CNetMsg);
                RoyalRumbleLeftCount(rmsg, leftcount);
                CNetMsg::SP killmsg(new CNetMsg);
                if(opc)
                    RoyalRumbleKillPlayer(killmsg, opc, df);
                switch(leveltype)
                {
                case LEVEL_TYPE_ROOKIE:
                {
                    gserver->m_RoyalRumble.m_pRookieArea->SendToAllClient(rmsg);
                    gserver->m_RoyalRumble.m_pRookieArea->SendToAllClient(killmsg);
                }
                break;
                case LEVEL_TYPE_SENIOR:
                {
                    gserver->m_RoyalRumble.m_pSeniorArea->SendToAllClient(rmsg);
                    gserver->m_RoyalRumble.m_pSeniorArea->SendToAllClient(killmsg);
                }
                break;
                case LEVEL_TYPE_MASTER:
                {
                    gserver->m_RoyalRumble.m_pMasterArea->SendToAllClient(rmsg);
                    gserver->m_RoyalRumble.m_pMasterArea->SendToAllClient(killmsg);
                }
                break;
                default:
                    break;
                }
            }
        }
        gserver->m_RoyalRumble.m_WaitPlayerList.DelNode(df->m_index);
    }
    if(opc && opc->m_pZone->IsWarGroundZone())
    {
        // 전장포인트 1포인트 지급
        opc->AddWarGroundPoint(1);

        // 전장 kill수 1 증가
        opc->AddKillCount(1);
    }

    ProcDeadQuestProc(df, opc);

    // rvr 룰 적용
    if (df->m_pZone->isRVRZone())
    {
        ProcRVR(df, of);
    }

    if( ArtifactManager::instance()->isOwnerPC(df->m_index) == true )
    {
        if(IS_PC(of))
        {
            //pvp를 당했는데 수비자가 유물을 갖고 있는 상태라면 공격자에게 아이템 양도
            ArtifactManager::instance()->hunt(df, TO_PC(of));
        }
        else
        {
            //이외에 죽임을 당했다면 아이템 서버로 반납
            ArtifactManager::instance()->dead(df);
        }
    }

#ifdef HARDCORE_SERVER
    if (gserver->m_hardcore_flag_in_gameserver)
    {
        switch (df->m_pZone->m_index )
        {
        case ZONE_START:
        {
            if (df->GetJoinFlag(df->m_pZone->m_index) == WCJF_NONE)	// 공성중이 아니고
            {
                if ( !(df->GetMapAttr() & MATT_FREEPKZONE) )
                {
                    df->m_desc->Make_1_Level();
                }
            }
        }
        break;

        case ZONE_FREE_PK_DUNGEON:
        case ZONE_PK_TOURNAMENT:
        case ZONE_ROYAL_RUMBLE:
        case ZONE_RVR:
            break;

        default:
        {
            if (df->GetJoinFlag(df->m_pZone->m_index) == WCJF_NONE)	// 공성중이 아니면
            {
                df->m_desc->Make_1_Level();
            }
        }
        break;
        } // end if
    }
#endif
}
示例#8
0
文件: editor.cpp 项目: Faultless/Dawn
void CEditor::DrawEditor()
{
  if (current_object == 3) {
    // we have selected to work with collisionboxes, draw them.
    for (unsigned int x = 0; x < zoneToEdit->CollisionMap.size(); x++) {
      if (objectedit_selected == (signed int)x) { // if we have a selected collisionbox, draw it a little brighter than the others.
        glColor4f(0.9f, 0.2f, 0.8f,0.8f);
      } else {
        glColor4f(0.7f, 0.1f, 0.6f, 0.8f);
      }

      DrawingHelpers::mapTextureToRect( interfacetexture.getTexture(4),
                                        zoneToEdit->CollisionMap[x].CR.x, zoneToEdit->CollisionMap[x].CR.w,
                                        zoneToEdit->CollisionMap[x].CR.y, zoneToEdit->CollisionMap[x].CR.h );
      glColor4f(1.0f,1.0f,1.0f,1.0f);
    }

    // draw interaction regions
    std::vector<InteractionRegion*> zoneInteractionRegions = zoneToEdit->getInteractionRegions();
    for ( size_t curInteractionRegionNr = 0; curInteractionRegionNr < zoneInteractionRegions.size(); ++curInteractionRegionNr )
    {
      InteractionRegion *curInteractionRegion = zoneInteractionRegions[ curInteractionRegionNr ];
      int left, bottom, width, height;
      curInteractionRegion->getPosition( left, bottom, width, height );
      if ( ! DrawingHelpers::isRectOnScreen(left-4, width+8, bottom-4, height+8) )
      {
        continue;
      }
      // draw border around the region
      glColor4f( 0.0f, 0.8f, 0.0f, 0.6f );
      DrawingHelpers::mapTextureToRect( interfacetexture.getTexture(4),
                                        left, width, bottom, height );
      // draw region
      if ( width > 8 && height > 8 )
      {
        glColor4f( 0.0f, 0.3f, 0.0f, 0.6f );
        DrawingHelpers::mapTextureToRect( interfacetexture.getTexture(4),
                                          left+4, width-8, bottom+4, height-8 );
      }

      // draw text for region
      if ( width > 28 and height > tinyFont->getHeight() * 3 + 8 )
      {
        glColor4f(1.0f,1.0f,1.0f,1.0f);

        std::string curEnterText = curInteractionRegion->getOnEnterText();
        std::string curLeaveText = curInteractionRegion->getOnLeaveText();
        bool printEnterAndLeaveText = ( curEnterText.size() > 0 && curLeaveText.size() > 0 && height > tinyFont->getHeight() * 6 );
        if ( curEnterText.size() > 0 )
        {
          std::string printText = std::string("Enter:\n").append(curEnterText);
          int printHeight = height - 8;
          int printBottom = bottom + 4;
          if ( printEnterAndLeaveText )
          {
            printBottom = printBottom - 4 + height - height/2;
            printHeight = (height-8) / 2;
          }
          printShortText( tinyFont, printText, left + 4, width - 8, printBottom, printHeight );
        }
        if ( curLeaveText.size() > 0 )
        {
          std::string printText = std::string("Leave:\n").append(curLeaveText);
          int printHeight = height - 8;
          int printBottom = bottom + 4;
          if ( printEnterAndLeaveText )
          {
            printHeight = (height-8) / 2;
          }
          printShortText( tinyFont, printText, left + 4, width - 8, printBottom, printHeight );
        }
      }
    }

    // NPCs. Show wander radius
    std::vector<CNPC*> npcs = zoneToEdit->getNPCs();
    for ( size_t curNPCNr=0; curNPCNr<npcs.size(); ++curNPCNr )
    {
      CNPC *curNPC = npcs[ curNPCNr ];
      int wanderRadius = curNPC->getWanderRadius();
      double rootX = curNPC->x_spawn_pos + curNPC->getWidth() / 2;
      double rootY = curNPC->y_spawn_pos + curNPC->getHeight() / 2;
      double collisionRadius = wanderRadius + 0.5*sqrt( curNPC->getWidth()*curNPC->getWidth() + curNPC->getHeight()*curNPC->getHeight() );
      glColor4f( 0.0f, 0.0f, 0.5f, 0.4f );
      DrawingHelpers::mapTextureToRect( interfacetexture.getTexture( 5 ),
                                        rootX-collisionRadius, 2*collisionRadius,
                                        rootY-collisionRadius, 2*collisionRadius );
    }
  }

  glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
  if (objectedit_selected >= 0) { // we have selected an object to edit it's properties, show the edit-screen.
    switch (current_object) {
    case 1:
      DrawEditFrame(&(zoneToEdit->EnvironmentMap[objectedit_selected]));
      break;
    case 2:
      DrawEditFrame(&(zoneToEdit->ShadowMap[objectedit_selected]));
      break;
    case 3:
      break;
    }
  }

  // quad on the top, baseframe for the object-selection.
  DrawingHelpers::mapTextureToRect( interfacetexture.getTexture(0),
                                    editorFocus->getX(), Configuration::screenWidth,
                                    editorFocus->getY()+Configuration::screenHeight-100, 100 );

  // quad on bottom, baseframe for our helptext.
  DrawingHelpers::mapTextureToRect( interfacetexture.getTexture(0),
                                    editorFocus->getX(), Configuration::screenWidth,
                                    editorFocus->getY(), 100 );

  int fontHeight = keybindingFont->getHeight();

  // display our general help text for the editor.
  glColor4f(1.0f,1.0f,0.13f,1.0f); // set yellow as font color
  keybindingFont->drawText(editorFocus->getX()+10, editorFocus->getY()+90 - fontHeight, "[ Scoll Up/Down ]  Select previous/next object");
  keybindingFont->drawText(editorFocus->getX()+10, editorFocus->getY()+80 - fontHeight, "[ F1 ]  Next set of objects");
  keybindingFont->drawText(editorFocus->getX()+10, editorFocus->getY()+70 - fontHeight, "[ DEL ]  Delete object at mouse position");
  keybindingFont->drawText(editorFocus->getX()+10, editorFocus->getY()+60 - fontHeight, "[ ENTER ]  Place object at mouse position");
  keybindingFont->drawText(editorFocus->getX()+10, editorFocus->getY()+50 - fontHeight, "[ S ]  Saves the changes into zone1-files");
  keybindingFont->drawText(editorFocus->getX()+10, editorFocus->getY()+40 - fontHeight, "[ O ]  Load a different zone (not yet implemented)");
  keybindingFont->drawText(editorFocus->getX()+10, editorFocus->getY()+30 - fontHeight, "[ L ]  Exit the editor");
  keybindingFont->drawText(editorFocus->getX()+10, editorFocus->getY()+20 - fontHeight, "//Press the left mouse button near the sides to scroll around ;-)");

  // if we have a selected object, display specific help text for it
  if (objectedit_selected >= 0) {
    glColor4f(0.5f,1.0f,0.5f,1.0f);
    keybindingFont->drawText(editorFocus->getX()+500, editorFocus->getY()+90 - fontHeight, "[ UP, DOWN, LEFT, RIGHT ]  Move the object");
    keybindingFont->drawText(editorFocus->getX()+500, editorFocus->getY()+80 - fontHeight, "[ Left Shift + UP, DOWN, LEFT, RIGHT ]  Change scale of object");
    keybindingFont->drawText(editorFocus->getX()+500, editorFocus->getY()+70 - fontHeight, "[ . ]  Increase transparency");
    keybindingFont->drawText(editorFocus->getX()+500, editorFocus->getY()+60 - fontHeight, "[ , ]  Decrease transparency");
    keybindingFont->drawText(editorFocus->getX()+500, editorFocus->getY()+50 - fontHeight, "[ 1/2/3 ]  Increase color RED/GREEN/BLUE");
    keybindingFont->drawText(editorFocus->getX()+500, editorFocus->getY()+40 - fontHeight, "[ Left Shift + 1/2/3 ]  Decrease color RED/GREEN/BLUE)");
    keybindingFont->drawText(editorFocus->getX()+500, editorFocus->getY()+30 - fontHeight, "[ b/n ] Increase / decrease Z-position");
  }

  glColor4f(1.0f,1.0f,1.0f,1.0f); // and back to white.

  DrawingHelpers::mapTextureToRect( interfacetexture.getTexture(1),
                                    editorFocus->getX()+(Configuration::screenWidth/2)-5, 50,
                                    editorFocus->getY()+Configuration::screenHeight-65, 50 );

  glBegin(GL_LINES);
  glTexCoord2f(0.0f, 0.0f);
  glVertex3f(mouseX-20+editorFocus->getX(), mouseY+editorFocus->getY(), 0.0f);
  glTexCoord2f(1.0f, 0.0f);
  glVertex3f(mouseX+20+editorFocus->getX(), mouseY+editorFocus->getY(), 0.0f);
  glTexCoord2f(0.0f, 0.0f);
  glVertex3f(mouseX+editorFocus->getX(), mouseY+20+editorFocus->getY(), 0.0f);
  glTexCoord2f(1.0f, 0.0f);
  glVertex3f(mouseX+editorFocus->getX(), mouseY-20+editorFocus->getY(), 0.0f);
  glEnd();

  TileSet* tileSet = EditorInterface::getTileSet();

  std::vector<Tile*> curTiles;

  switch (current_object)
  {
  case 0:
    // draw all tileset tiles in edit frame
    curTiles = tileSet->getAllTilesOfType( TileClassificationType::FLOOR );
    break;

  case 1:
    // draw all environment objects in edit frame
    curTiles = tileSet->getAllTilesOfType( TileClassificationType::ENVIRONMENT );
    break;

  case 2:
    // draw all available shadows in edit frame
    curTiles = tileSet->getAllTilesOfType( TileClassificationType::SHADOW );
    break;
  case 4:
    // we have selected to work with NPCs, draw their bases
    for ( size_t curNPC = 0; curNPC < editorNPCs.size(); curNPC++ ) {
      int npcWidth = editorNPCs[ curNPC ].second->getTexture( ActivityType::Walking )->getTexture( 5 ).width;
      int npcHeight = editorNPCs[ curNPC ].second->getTexture( ActivityType::Walking )->getTexture( 5 ).height;
      DrawingHelpers::mapTextureToRect( editorNPCs[ curNPC ].second->getTexture( ActivityType::Walking )->getTexture( 5 ),
                                        editorFocus->getX()+(Configuration::screenWidth/2)+(curNPC*50)+(tilepos_offset*50)-48+20, npcWidth,
                                        editorFocus->getY()+Configuration::screenHeight-40-48, npcHeight );

    };
    keybindingFont->drawText( editorFocus->getX()+(Configuration::screenWidth/2)-5, editorFocus->getY()+Configuration::screenHeight-90, editorNPCs[ current_tilepos ].first );
    keybindingFont->drawText( editorFocus->getX()+(Configuration::screenWidth/2)-5, editorFocus->getY()+Configuration::screenHeight-100, "Level: %d (%s)", editorNPCs[ current_tilepos ].second->getLevel(), CharacterClass::getCharacterClassName( editorNPCs[ current_tilepos ].second->getClass() ).c_str() );
    break;
  }

  for ( tilepos=0; tilepos<curTiles.size(); ++tilepos ) {
    Tile *curTile = curTiles[ tilepos ];
    DrawingHelpers::mapTextureToRect( curTile->texture->getTexture(0),
                                      editorFocus->getX()+(Configuration::screenWidth/2)+(tilepos*50)+(tilepos_offset*50), 40,
                                      editorFocus->getY()+Configuration::screenHeight-60, 40 );
  }

  /// draw the world position of the mouse in the top left corner.
  keybindingFont->drawText( editorFocus->getX()+10, editorFocus->getY()+Configuration::screenHeight-10, "x: %d, y: %d", int(editorFocus->getX())+mouseX, int(editorFocus->getY())+mouseY );
}
示例#9
0
文件: editor.cpp 项目: Faultless/Dawn
void CEditor::HandleKeys()
{
  Uint8* keys;
  keys = SDL_GetKeyState(NULL);
  SDL_Event event;

  // the hot spot for mouse scrolling, you need to press the left mouse button within this area on whatever side
  int scrollHotSpot = 30;

  while (SDL_PollEvent(&event)) {
    if (event.type == SDL_QUIT)  {
      done = 1;
    }

    if (event.type == SDL_KEYDOWN) {
      if (event.key.keysym.sym == SDLK_SPACE) { }
    }

    if (event.type == SDL_MOUSEBUTTONDOWN) {
      switch (event.button.button) {
      case SDL_BUTTON_LEFT: // mouse button 1
      {
        int previous_objectedit_selected = objectedit_selected;
        bool handled = false;
        // see if we can select an object being pointed at.
        if ( ! handled ) {
          switch (current_object) {
          case 1: // environment
            objectedit_selected = zoneToEdit->LocateEnvironment(editorFocus->getX()+mouseX,editorFocus->getY()+mouseY);
            break;
          case 2: // shadows
            objectedit_selected = zoneToEdit->LocateShadow(editorFocus->getX()+mouseX,editorFocus->getY()+mouseY);
            break;
          case 3: // collisionboxes
            objectedit_selected = zoneToEdit->LocateCollisionbox(editorFocus->getX()+mouseX,editorFocus->getY()+mouseY);
            break;
          case 4: // NPCs
            objectedit_selected = zoneToEdit->LocateNPC(editorFocus->getX()+mouseX,editorFocus->getY()+mouseY);
          default:
            curAdjacentTiles.clear();
            break;
          }
        }
        if ( previous_objectedit_selected != objectedit_selected )
        {
          // something new was selected. Update adjacency-list if necessary
          if ( adjacencyModeEnabled )
          {
            updateAdjacencyList();
          }
        }
      }
      break;

      case SDL_BUTTON_RIGHT: // right mouse button.
      {
        bool handled = false;
        // first check whether we are in adjacency mode and can place a tile. If not we select a tile
        if ( ! handled && adjacencyModeEnabled ) {
          handled = checkAndPlaceAdjacentTile();
        }
      }
      break;

      case SDL_BUTTON_WHEELUP: // scroll up
      {
        // if mouse is over a tile for adjacency selection, change to next tile in the selection
        // else increase our tileposition
        bool handled = false;
        if ( adjacencyModeEnabled ) {
          handled = checkAndApplyAdjacencyModification( 1 );
        }
        if ( ! handled ) {
          inc_tilepos();
        }
      }
      break;

      case SDL_BUTTON_WHEELDOWN: // scroll down
      {
        // if mouse is over a tile for adjacency selection, change to previous tile in the selection
        // else decrease our tileposition
        bool handled = false;
        if ( adjacencyModeEnabled ) {
          handled = checkAndApplyAdjacencyModification( -1 );
        }
        if ( ! handled ) {
          dec_tilepos();
        }
      }
      break;
      }
    }

    if (event.type == SDL_MOUSEMOTION) {
      mouseX = event.motion.x;
      mouseY = Configuration::screenHeight - event.motion.y - 1;
    }
  }

  // the arrow-keys. if an object is selected, we move it around. if Left shift is pushed, we scale the object..
  // else we move around in our zone.

  if (objectedit_selected >= 0 && !KP_moveonce) {
    switch (current_object) {
    case 1: // environment
      if (keys[SDLK_LSHIFT]) {
        if (keys[SDLK_DOWN]) {
          zoneToEdit->EnvironmentMap[objectedit_selected].y_scale -= 0.01f;
        }
        if (keys[SDLK_UP]) {
          zoneToEdit->EnvironmentMap[objectedit_selected].y_scale += 0.01f;
        }
        if (keys[SDLK_LEFT]) {
          zoneToEdit->EnvironmentMap[objectedit_selected].x_scale -= 0.01f;
        }
        if (keys[SDLK_RIGHT]) {
          zoneToEdit->EnvironmentMap[objectedit_selected].x_scale += 0.01f;
        }
      } else {
        if (keys[SDLK_RCTRL]) // right ctrl is held down, then we only want to move environment 1 pixel at time
        {
          KP_moveonce = true;
        }
        if (keys[SDLK_DOWN]) {
          zoneToEdit->EnvironmentMap[objectedit_selected].y_pos--;
        }
        if (keys[SDLK_UP]) {
          zoneToEdit->EnvironmentMap[objectedit_selected].y_pos++;
        }
        if (keys[SDLK_LEFT]) {
          zoneToEdit->EnvironmentMap[objectedit_selected].x_pos--;
        }
        if (keys[SDLK_RIGHT]) {
          zoneToEdit->EnvironmentMap[objectedit_selected].x_pos++;
        }
      }
      break;
    case 2: // shadows
      if (keys[SDLK_LSHIFT]) {
        if (keys[SDLK_DOWN]) {
          zoneToEdit->ShadowMap[objectedit_selected].y_scale -= 0.01f;
        }
        if (keys[SDLK_UP]) {
          zoneToEdit->ShadowMap[objectedit_selected].y_scale += 0.01f;
        }
        if (keys[SDLK_LEFT]) {
          zoneToEdit->ShadowMap[objectedit_selected].x_scale -= 0.01f;
        }
        if (keys[SDLK_RIGHT]) {
          zoneToEdit->ShadowMap[objectedit_selected].x_scale += 0.01f;
        }
      } else {
        if (keys[SDLK_DOWN]) {
          zoneToEdit->ShadowMap[objectedit_selected].y_pos--;
        }
        if (keys[SDLK_UP]) {
          zoneToEdit->ShadowMap[objectedit_selected].y_pos++;
        }
        if (keys[SDLK_LEFT]) {
          zoneToEdit->ShadowMap[objectedit_selected].x_pos--;
        }
        if (keys[SDLK_RIGHT]) {
          zoneToEdit->ShadowMap[objectedit_selected].x_pos++;
        }
      }
      break;
    case 3: // collisionboxes
      if (keys[SDLK_LSHIFT]) {
        if (keys[SDLK_DOWN]) {
          zoneToEdit->CollisionMap[objectedit_selected].CR.h -= 1;
        }
        if (keys[SDLK_UP]) {
          zoneToEdit->CollisionMap[objectedit_selected].CR.h += 1;
        }
        if (keys[SDLK_LEFT]) {
          zoneToEdit->CollisionMap[objectedit_selected].CR.w -= 1;
        }
        if (keys[SDLK_RIGHT]) {
          zoneToEdit->CollisionMap[objectedit_selected].CR.w += 1;
        }
      } else {
        if (keys[SDLK_DOWN]) {
          zoneToEdit->CollisionMap[objectedit_selected].CR.y--;
        }
        if (keys[SDLK_UP]) {
          zoneToEdit->CollisionMap[objectedit_selected].CR.y++;
        }
        if (keys[SDLK_LEFT]) {
          zoneToEdit->CollisionMap[objectedit_selected].CR.x--;
        }
        if (keys[SDLK_RIGHT]) {
          zoneToEdit->CollisionMap[objectedit_selected].CR.x++;
        }
      }
      break;
    case 4: // NPCs
      if (keys[SDLK_DOWN]) {
        zoneToEdit->getNPCs()[ objectedit_selected ]->y_spawn_pos--;
        zoneToEdit->getNPCs()[ objectedit_selected ]->y_pos--;
      }
      if (keys[SDLK_UP]) {
        zoneToEdit->getNPCs()[ objectedit_selected ]->y_spawn_pos++;
        zoneToEdit->getNPCs()[ objectedit_selected ]->y_pos++;
      }
      if (keys[SDLK_LEFT]) {
        zoneToEdit->getNPCs()[ objectedit_selected ]->x_spawn_pos--;
        zoneToEdit->getNPCs()[ objectedit_selected ]->x_pos--;
      }
      if (keys[SDLK_RIGHT]) {
        zoneToEdit->getNPCs()[ objectedit_selected ]->x_spawn_pos++;
        zoneToEdit->getNPCs()[ objectedit_selected ]->x_pos++;
      }
      break;
    }
  } else if ( objectedit_selected < 0 ) { // Not editting an object, use arrows to move screen


    if(SDL_GetMouseState(NULL, NULL) &SDL_BUTTON(1))
    {
      //corners
      if(mouseX < scrollHotSpot && mouseY < scrollHotSpot)                    editorFocus->setFocus(editorFocus->getX()-1, editorFocus->getY()-1);  //bottom-left
      else if(mouseX < scrollHotSpot && mouseY > Configuration::screenHeight-scrollHotSpot)         editorFocus->setFocus(editorFocus->getX()-1, editorFocus->getY()+1);  //top-left
      else if(mouseX > Configuration::screenWidth-scrollHotSpot && mouseY < scrollHotSpot)         editorFocus->setFocus(editorFocus->getX()+1, editorFocus->getY()-1);  //bottom-right
      else if(mouseX > Configuration::screenWidth-scrollHotSpot && mouseY > Configuration::screenHeight-scrollHotSpot)   editorFocus->setFocus(editorFocus->getX()+1, editorFocus->getY()+1);  //top-right
      else
      {
        //sides
        if(mouseX < scrollHotSpot)        editorFocus->setFocus(editorFocus->getX()-1, editorFocus->getY()); //left
        if(mouseX > Configuration::screenWidth-scrollHotSpot)  editorFocus->setFocus(editorFocus->getX()+1, editorFocus->getY()); //right
        if(mouseY < scrollHotSpot)        editorFocus->setFocus(editorFocus->getX(), editorFocus->getY()-1); //bottom
        if(mouseY > Configuration::screenHeight-scrollHotSpot)  editorFocus->setFocus(editorFocus->getX(), editorFocus->getY()+1); //top
      }
    }

    if (keys[SDLK_DOWN]) {
      editorFocus->setFocus(editorFocus->getX(), editorFocus->getY()-2);
    }
    if (keys[SDLK_UP]) {
      editorFocus->setFocus(editorFocus->getX(), editorFocus->getY()+2);
    }
    if (keys[SDLK_LEFT]) {
      editorFocus->setFocus(editorFocus->getX()-2, editorFocus->getY());
    }
    if (keys[SDLK_RIGHT]) {
      editorFocus->setFocus(editorFocus->getX()+2, editorFocus->getY());
    }
  }

  if (!keys[SDLK_DOWN] && !keys[SDLK_UP] && !keys[SDLK_LEFT] && !keys[SDLK_RIGHT])
  {
    KP_moveonce = false;
  }

  if (keys[SDLK_DELETE] && !KP_delete_environment) {
    KP_delete_environment = true;
    switch (current_object) {
    case 0: // tiles
      zoneToEdit->DeleteTile(zoneToEdit->LocateTile(editorFocus->getX()+mouseX,editorFocus->getY()+mouseY));
      break;
    case 1: // environment
      if ( zoneToEdit->DeleteEnvironment(editorFocus->getX()+mouseX,editorFocus->getY()+mouseY) == 0 )
        objectedit_selected = -1;
      break;
    case 2: // shadows
      if ( zoneToEdit->DeleteShadow(editorFocus->getX()+mouseX,editorFocus->getY()+mouseY) == 0 )
        objectedit_selected = -1;
      break;
    case 3: // collisionboxes
      if ( zoneToEdit->DeleteCollisionbox(editorFocus->getX()+mouseX,editorFocus->getY()+mouseY) == 0 )
        objectedit_selected = -1;
      break;
    case 4: // NPCs
      if ( zoneToEdit->DeleteNPC(editorFocus->getX()+mouseX,editorFocus->getY()+mouseY) == 0 )
      {
        zoneToEdit->cleanupNPCList();
        objectedit_selected = -1;
      }
      break;
    }
  }

  if (!keys[SDLK_DELETE]) {
    KP_delete_environment = false;
  }

  if (keys[SDLK_RETURN] && !KP_add_environment) {
    objectedit_selected = -1;
    KP_add_environment = true;

    switch (current_object) {
    case 0: // tiles
    {
      Tile *currentTile = EditorInterface::getTileSet()->getAllTilesOfType( TileClassificationType::FLOOR )[ current_tilepos ];
      zoneToEdit->ChangeTile(zoneToEdit->LocateTile(editorFocus->getX()+mouseX,editorFocus->getY()+mouseY),currentTile);
    }
    break;
    case 1: // environment
    {
      Tile *currentTile = EditorInterface::getTileSet()->getAllTilesOfType( TileClassificationType::ENVIRONMENT )[ current_tilepos ];
      zoneToEdit->AddEnvironment(editorFocus->getX()+mouseX,editorFocus->getY()+mouseY,currentTile, true /* centered on pos */ );
    }
    break;
    case 2: // shadows
    {
      Tile *currentTile = EditorInterface::getTileSet()->getAllTilesOfType( TileClassificationType::SHADOW )[ current_tilepos ];
      zoneToEdit->AddShadow(editorFocus->getX()+mouseX,editorFocus->getY()+mouseY,currentTile);
    }
    break;
    case 3: // collisionboxes
      zoneToEdit->AddCollisionbox(editorFocus->getX()+mouseX,editorFocus->getY()+mouseY);
      break;
    case 4: // NPCs
      CNPC *curNPC = DawnInterface::addMobSpawnPoint( editorNPCs[ current_tilepos ].first, editorFocus->getX()+mouseX-48, editorFocus->getY()+mouseY-48, 180, 1 );
      curNPC->setAttitude( Attitude::HOSTILE );
      break;
    }
  }

  if (!keys[SDLK_RETURN]) {
    KP_add_environment = false;
  }

  if (keys[SDLK_l] && !KP_toggle_editor) {
    current_tilepos = 0;
    tilepos_offset = 0;
    objectedit_selected = -1;
    enabled = false;
    KP_toggle_editor = true;
    *editorFocus = *originalFocus;
    delete originalFocus;
  }

  if (!keys[SDLK_l]) {
    KP_toggle_editor = false;
  }

  if (keys[SDLK_m] && !KP_toggle_adjacencyMode) {
    KP_toggle_adjacencyMode = true;
    adjacencyModeEnabled = ! adjacencyModeEnabled;
    if ( adjacencyModeEnabled )
    {
      updateAdjacencyList();
    }
  }

  if (!keys[SDLK_m]) {
    KP_toggle_adjacencyMode = false;
  }

  if (keys['.']) {  // increase the amount of transparency of the object.
    switch (current_object) {
    case 1: // environment
      if (zoneToEdit->EnvironmentMap[objectedit_selected].transparency > 0.01f) {
        zoneToEdit->EnvironmentMap[objectedit_selected].transparency -= 0.01f;
      }
      break;
    case 2: // shadows
      if (zoneToEdit->ShadowMap[objectedit_selected].transparency > 0.01f) {
        zoneToEdit->ShadowMap[objectedit_selected].transparency -= 0.01f;
      }
      break;
    }
  }

  if (keys[',']) { // decrease the amount of transparency of the object.
    switch (current_object) {
    case 1: // environment
      if (zoneToEdit->EnvironmentMap[objectedit_selected].transparency < 0.99f) {
        zoneToEdit->EnvironmentMap[objectedit_selected].transparency += 0.01f;
      }
      break;
    case 2: // shadows
      if (zoneToEdit->ShadowMap[objectedit_selected].transparency < 0.99f) {
        zoneToEdit->ShadowMap[objectedit_selected].transparency += 0.01f;
      }
      break;
    }
  }

  // change the objects red color
  if (keys['1']) {
    switch (current_object) {
    case 1:
      if (keys[SDLK_LSHIFT]) {
        if (zoneToEdit->EnvironmentMap[objectedit_selected].red > 0.01f) {
          zoneToEdit->EnvironmentMap[objectedit_selected].red -= 0.01f;
        }
      } else {
        if (zoneToEdit->EnvironmentMap[objectedit_selected].red < 1.0f) {
          zoneToEdit->EnvironmentMap[objectedit_selected].red += 0.01f;
        }
      }
      break;
    case 2:
      if (keys[SDLK_LSHIFT]) {
        if (zoneToEdit->ShadowMap[objectedit_selected].red > 0.01f) {
          zoneToEdit->ShadowMap[objectedit_selected].red -= 0.01f;
        }
      } else {
        if (zoneToEdit->ShadowMap[objectedit_selected].red < 1.0f) {
          zoneToEdit->ShadowMap[objectedit_selected].red += 0.01f;
        }
      }
      break;
    }
  }

  // change the objects green color
  if (keys['2']) {
    switch (current_object) {
    case 1:
      if (keys[SDLK_LSHIFT]) {
        if (zoneToEdit->EnvironmentMap[objectedit_selected].green > 0.01f) {
          zoneToEdit->EnvironmentMap[objectedit_selected].green -= 0.01f;
        }
      } else {
        if (zoneToEdit->EnvironmentMap[objectedit_selected].green < 1.0f) {
          zoneToEdit->EnvironmentMap[objectedit_selected].green += 0.01f;
        }
      }
      break;
    case 2:
      if (keys[SDLK_LSHIFT]) {
        if (zoneToEdit->ShadowMap[objectedit_selected].green > 0.01f) {
          zoneToEdit->ShadowMap[objectedit_selected].green -= 0.01f;
        }
      } else {
        if (zoneToEdit->ShadowMap[objectedit_selected].green < 1.0f) {
          zoneToEdit->ShadowMap[objectedit_selected].green += 0.01f;
        }
      }
      break;
    }
  }

  // change the objects blue color
  if (keys['3']) {
    switch (current_object) {
    case 1:
      if (keys[SDLK_LSHIFT]) {
        if (zoneToEdit->EnvironmentMap[objectedit_selected].blue > 0.01f) {
          zoneToEdit->EnvironmentMap[objectedit_selected].blue -= 0.01f;
        }
      } else {
        if (zoneToEdit->EnvironmentMap[objectedit_selected].blue < 1.0f) {
          zoneToEdit->EnvironmentMap[objectedit_selected].blue += 0.01f;
        }
      }
      break;
    case 2:
      if (keys[SDLK_LSHIFT]) {
        if (zoneToEdit->ShadowMap[objectedit_selected].blue > 0.01f) {
          zoneToEdit->ShadowMap[objectedit_selected].blue -= 0.01f;
        }
      } else {
        if (zoneToEdit->ShadowMap[objectedit_selected].blue < 1.0f) {
          zoneToEdit->ShadowMap[objectedit_selected].blue += 0.01f;
        }
      }
      break;
    }
  }

  // increase the Z-position
  if (keys[SDLK_b] && !KP_increase_Zpos)
  {
    KP_increase_Zpos = true;
    if ( current_object == 1 ) // environment
    {
      zoneToEdit->EnvironmentMap[objectedit_selected].z_pos++;
    }
  }

  if (!keys[SDLK_b])
  {
    KP_increase_Zpos = false;
  }

  // decrease the Z-position
  if (keys[SDLK_n] && !KP_decrease_Zpos)
  {
    KP_decrease_Zpos = true;

    if ( current_object == 1 ) // environment
    {
      if ( zoneToEdit->EnvironmentMap[objectedit_selected].z_pos > 0  )
      {
        zoneToEdit->EnvironmentMap[objectedit_selected].z_pos--;
      }
    }
  }

  if (!keys[SDLK_n])
  {
    KP_decrease_Zpos = false;
  }

  if (keys[SDLK_F1] && !KP_toggle_tileset) {
    current_tilepos = 0;
    tilepos_offset = 0;
    objectedit_selected = -1;

    KP_toggle_tileset = true;
    if (current_object < 4) {
      current_object++;
    } else {
      current_object = 0;
    }
  }

  if (!keys[SDLK_F1]) {
    KP_toggle_tileset = false;
  }

  if (keys[SDLK_s] && !KP_save_zone) {
    KP_save_zone = true;
    SaveZone();
    message.AddText(editorFocus->getX() + (Configuration::screenWidth/2), editorFocus->getY() + (Configuration::screenHeight/2), 1.0f, 0.625f, 0.71f, 1.0f, 15, 3.0f, "Zone saved ...");
  }

  if (!keys[SDLK_s]) {
    KP_save_zone = false;
  }

}
void ProcDead(CNPC* df, CCharacter* of)
{
	CPC*		opc				= NULL;
	CNPC*		onpc			= NULL;
	CPet*		opet			= NULL;
	CElemental*	oelemental		= NULL;
	CAPet*		oapet			= NULL;

	bool bNPCKilledNPC = false; // npc가 npc를 죽인 경우 꼭 이것을 true로 해줘야한다.

	switch (of->m_type)
	{
	case MSG_CHAR_PC:
		opc = TO_PC(of);
		if (opc == NULL)
			goto END_PROC;
		break;

	case MSG_CHAR_NPC:
		onpc = TO_NPC(of);
		break;

	case MSG_CHAR_PET:
		opet = TO_PET(of);
		opc = opet->GetOwner();
		if (opc == NULL)
			goto END_PROC;
		break;

	case MSG_CHAR_ELEMENTAL:
		oelemental = TO_ELEMENTAL(of);
		opc = oelemental->GetOwner();
		if (opc == NULL)
			goto END_PROC;
		break;
	case MSG_CHAR_APET:
		oapet	= TO_APET(of);
		opc		= oapet->GetOwner();
		if( opc == NULL )
			goto END_PROC;
		break;

	default:
		goto END_PROC;
	}
#ifdef SYSTEM_TREASURE_MAP
//	if( df->m_idNum == TREASURE_BOX_NPC_INDEX)	 // 보물상자 npc를 잡았다. 정보를 없애주자.
//		df->m_pZone->RemoveTreasureBoxNpc(df );
#endif

	// 공주구출 퀘스트 (퍼스널 던전 2) 실패
	ProcDead_PD2(df);

	// 죽은 것이 테이밍 몬스터일 경우
	if (df->Check_MobFlag( STATE_MONSTER_TAMING ) )
	{
		CPC* owner = NULL;			// 몬스터를 테이밍한 캐릭터
		owner = df->GetOwner();		// 몬스터가 테이밍 되었는지 확인

		// 주인이 공격하고 있는 타겟을 지워준다. 주인이 테이밍 중이 아닌걸로 바꿔준다.
		if ( owner )
		{
			owner->DeleteSlave( df );
		}
		goto SKIP_DROP;
	}

	// 죽인 것이 테이밍 몬스터일 경우
	if (onpc && onpc->Check_MobFlag( STATE_MONSTER_TAMING ) )
	{
		CPC* owner = NULL;				// 몬스터를 테이밍한 캐릭터
		owner = onpc->GetOwner();		// 몬스터가 테이밍 되었는지 확인

		// 주인이 공격하고 있는 타겟을 지워준다.
		if ( owner )
		{
			owner->SetOwners_target(NULL);
			// opc에 주인을 넣어준다.
			opc = owner;
			bNPCKilledNPC = true;
		}
		else
			goto SKIP_DROP;
	}
	else if( onpc && onpc->GetOwner() ) // 공격한 NPC가 오너가 있다면
	{
		CNPC* sumNpc = onpc->GetOwner()->GetSummonNpc(onpc);
		if( sumNpc )
		{
			if( sumNpc->Check_MobFlag((STATE_MONSTER_MERCENARY)) )
			{
				sumNpc->GetOwner()->SetSummonOwners_target(NULL);
			}

			opc = onpc->GetOwner();
			bNPCKilledNPC = true;
		}
		else
			goto SKIP_DROP;
	}

	if( df && df->GetOwner() ) // 죽은 넘이 owner 있다면
	{
		if( df->Check_MobFlag(STATE_MONSTER_PARASITE) ) // 패러사이트에 걸려있다면.
		{
			int parasiteCnt = GetRandom(0,3);
			parasiteCnt -= df->GetOwner()->GetBombSummonCont();
			if( parasiteCnt > 0 )
			{
				int parasiteIdx = df->m_assist.GetSummonNpcIndex();
				if( parasiteIdx > 0 )
				{
					int i;
					for(i=0; i<parasiteCnt; i++)
					{
						CNPC* pParasiteNPC;
						pParasiteNPC = gserver->m_npcProtoList.Create(parasiteIdx, NULL );
						if( pParasiteNPC == NULL )
							continue;

						GET_X(pParasiteNPC) = GET_X(df);
						GET_Z(pParasiteNPC) = GET_Z(df);
						GET_R(pParasiteNPC) = GET_R(df);
						GET_YLAYER(pParasiteNPC) = GET_YLAYER(df);

						float fRand = GetRandom(0,1) ? 1.0f : -1.0f ;
						float x  = 2.0f + ( fRand * (float)(GetRandom( 0 , 200 ) / 100.0f) );
						fRand = GetRandom(0,1) ? 1 : -1 ;
						float z  = 2.0f + ( fRand * (float)(GetRandom( 0 , 200 ) / 100.0f) );

						pParasiteNPC->m_regenX = GET_X(pParasiteNPC) += x;
						pParasiteNPC->m_regenZ = GET_Z(pParasiteNPC) += z;
						pParasiteNPC->m_regenY = GET_YLAYER(pParasiteNPC);

						pParasiteNPC->CalcStatus(false);

						CSkill * pSkill = gserver->m_skillProtoList.Create( 1133 ); // 자살 공격
						if( pSkill == NULL )
						{
							delete pParasiteNPC ;
							pParasiteNPC = NULL;
							continue;
						}

						pParasiteNPC->SetOwner(df->GetOwner());

						bool bApply;
						if( 0 != ApplySkill((CCharacter*)df->GetOwner(), (CCharacter*)pParasiteNPC, pSkill, -1, bApply) )
						{
							delete pSkill;
							pSkill = NULL;

							delete pParasiteNPC;

							continue;
						}
						delete pSkill;
						pSkill = NULL;

						if( bApply == false )
						{
							delete pParasiteNPC ;
							pParasiteNPC = NULL;
							continue;
						}
						df->GetOwner()->SetBombSummonNPC(pParasiteNPC);

						int cx, cz;
						df->m_pArea->AddNPC(pParasiteNPC);
						df->m_pArea->PointToCellNum(GET_X(pParasiteNPC), GET_Z(pParasiteNPC), &cx, &cz);
						df->m_pArea->CharToCell(pParasiteNPC, GET_YLAYER(pParasiteNPC), cx, cz);

						{
							CNetMsg::SP rmsg(new CNetMsg);
							AppearMsg(rmsg, pParasiteNPC, true);
							df->m_pArea->SendToCell(rmsg, GET_YLAYER(pParasiteNPC), cx, cz);
						}
					}
				}
			}
		}

		CNPC* sumNpc = df->GetOwner()->GetSummonNpc(df);
		if( sumNpc )
		{
#ifdef BUGFIX_MERCNERAY_DELETE
			sumNpc->GetOwner()->SummonNpcRemove(df, false);
#else
			sumNpc->GetOwner()->SummonNpcRemove(df);
#endif
			goto SKIP_DROP;
		}
	}
	/*

	*/

	// 이곳으로 넘어오면 테이밍이 아니므로, 모든 몬스터는 몬스터에게 죽으면 패스
	else if (onpc && !bNPCKilledNPC)
	{
		goto SKIP_DROP;
	}

	// pc가 npc를 죽이면 테이밍 몬스터의 타겟을 지워준다.
	if (opc)
	{
		opc->SetOwners_target(NULL);
		opc->SetSummonOwners_target(NULL);
	}

	// 리더 사망시 처리
	if (!df->m_proto->CheckFlag(NPC_RAID))
		ProcFollowNPC(df);

	// 공성 포인트 계산
	if (opc)
		CalcWarPoint(opc, df);

	// 죽은 NPC가 공성탑이나 수호병이 아닐 경우 처리
	if (!df->m_proto->CheckFlag(NPC_CASTLE_TOWER | NPC_CASTLE_GUARD))
	{
		int level = -1;
		LONGLONG nTotalDamage = 0;
		// 우선권 PC, 평균 레벨 구하기
		CPC* tpc = FindPreferencePC(df, &level, &nTotalDamage);
#ifdef GER_LOG
		if( IS_PC( of ))
		{
			CPC *user = TO_PC( of );
			GAMELOGGEM << init( 0, "CHAR_VICTORY" )
					   << LOG_VAL("account-id", user->m_desc->m_idname ) << blank
					   << LOG_VAL("character-id", user->m_desc->m_pChar->m_name ) << blank
					   << LOG_VAL("zone-id", user->m_desc->m_pChar->m_pZone->m_index ) << blank
					   << LOG_VAL("victim-id", df->m_index ) << blank
					   /*<< LOG_VAL("opponent-id", kill) << blank*/
					   << LOG_VAL("longitude", GET_X(user) ) << blank
					   << LOG_VAL("latitude", GET_Z(user) ) << blank
					   << endGer;
		}
#endif
		// 보스몹
		if (df->m_proto->CheckFlag(NPC_BOSS | NPC_MBOSS | NPC_RAID))
		{
			GAMELOG << init("MOB DEAD")
					<< "INDEX" << delim
					<< df->m_proto->m_index << delim
					<< "NAME" << delim
					<< df->m_name << delim
					<< "ZONE" << delim
					<< df->m_pZone->m_index << delim
					<< "POSITION" << delim
					<< GET_X(df) << delim
					<< GET_Z(df) << delim
					<< GET_YLAYER(df) << delim
					<< "KILL BY" << delim;
			if (opc)
			{
				GAMELOG << opc->m_index << delim
						<< opc->m_name << delim
						<< opc->m_nick << delim
						<< opc->m_job << delim
						<< opc->m_job2 << delim
						<< opc->m_level;
			}
			else
			{
				GAMELOG << of->m_type << delim
						<< of->m_index << delim
						<< of->m_name << delim
						<< of->m_level;
			}
			GAMELOG << end;

			if (df->m_proto->CheckFlag(NPC_BOSS | NPC_MBOSS))
			{
				// 카오 성향 회복 : 보스몹을 잡으면 회복 보너스
				if (opc && opc->IsChaotic() && tpc == opc)
				{
					if( !gserver->m_bNonPK )
						opc->m_pkPenalty += df->m_level / 10;

					if (opc->m_pkPenalty > 0)
						opc->m_pkPenalty = 0;

					{
						CNetMsg::SP rmsg(new CNetMsg);
						CharStatusMsg(rmsg, opc, 0);
						opc->m_pArea->SendToCell(rmsg, opc, false);
					}

					opc->m_bChangeStatus = true;
				}
			}
		} // 보스몹

		if(opc && opc->m_pArea && df->m_proto->m_index == 1002 && df->m_pZone && df->m_pZone->m_index == ZONE_ALTER_OF_DARK)
		{
			// 네임드 몬스터 죽은 것으로 체크
			opc->m_pArea->m_CTriggerList.Set_TriggerFlag(TRIGGER_FLAG_NAMEDNPC_DEATH1);
			opc->m_pArea->m_CTriggerList.Set_TriggerFlag(TRIGGER_FLAG_NAMEDNPC_DEATH1002_BEFORE);
			opc->m_pArea->m_CTriggerList.SaveTriggerInfo(TRIGGER_SAVE_ALTER_OF_DARK_1002, opc->m_nJoinInzone_RoomNo);	//트리거 정보 저장
			opc->m_pArea->Change_NpcRegenRaid(TRIGGER_SAVE_ALTER_OF_DARK_1002, 1002);
		}
		else if(opc && opc->m_pArea && df->m_proto->m_index == 1003 && df->m_pZone && df->m_pZone->m_index == ZONE_ALTER_OF_DARK)
		{
			// 네임드 몬스터 죽은 것으로 체크
			opc->m_pArea->m_CTriggerList.Set_TriggerFlag(TRIGGER_FLAG_NAMEDNPC_DEATH2);
			opc->m_pArea->m_CTriggerList.Set_TriggerFlag(TRIGGER_FLAG_NAMEDNPC_DEATH1003_BEFORE);
			opc->m_pArea->m_CTriggerList.SaveTriggerInfo(TRIGGER_SAVE_ALTER_OF_DARK_1003, opc->m_nJoinInzone_RoomNo);	//트리거 정보 저장
			opc->m_pArea->Change_NpcRegenRaid(TRIGGER_SAVE_ALTER_OF_DARK_1003, 1003);
		}
		else if(opc && opc->m_pArea && df->m_proto->m_index == 1018 && df->m_pZone && df->m_pZone->m_index == ZONE_ALTER_OF_DARK)
		{
			// 네임드 몬스터 죽은 것으로 체크
			opc->m_pArea->m_CTriggerList.Set_TriggerFlag(TRIGGER_FLAG_NAMEDNPC_DEATH1018_BEFORE);
			opc->m_pArea->m_CTriggerList.SaveTriggerInfo(TRIGGER_SAVE_ALTER_OF_DARK_1018, opc->m_nJoinInzone_RoomNo);	//트리거 정보 저장
			opc->m_pArea->Change_NpcRegenRaid(TRIGGER_SAVE_ALTER_OF_DARK_1018, 1018);
		}
		else if (opc && opc->m_pArea && df->m_proto->m_index == 963 && df->m_pZone && df->m_pZone->m_index == ZONE_CAPPELLA_1)
		{
			// 트리거를 사용하기 위한 npc963 죽은 count 세기
			opc->m_pArea->m_CTriggerList.m_nNPC963_KilledCount += 1;
		}

		int nObjectData;
		int nAkanNpcIdx = df->m_proto->m_index;

		switch(nAkanNpcIdx)
		{
		case 1115:				// 파독스의 인형(Hard)
		case 1170:				// 파독스의 인형(Normal)
			{
				nObjectData = 10;
				if(opc && opc->m_pArea && df->m_pZone && df->m_pZone->m_index == ZONE_AKAN_TEMPLE)
				{
					CNetMsg::SP rmsg(new CNetMsg);
					RaidSceneMsg(rmsg, OBJECT_TYPE_TODO, KILL_NPC, nAkanNpcIdx, nObjectData);
					do_ExRaidScene(opc, rmsg);
				}
			}
			break;
		case 1112:				// 툴만
		case 1116:				// 파독스
		case 1120:				// 쿤타
		case 1124:				// 유작
		case 1126:				// 고위 연금술사 제롬
		case 1127:				// 고위 마법술사 미엘
		case 1128:				// 제사장 미쿠
		case 1167:				// 툴만
		case 1171:				// 파독스
		case 1175:				// 쿤타
		case 1179:				// 유작
		case 1180:				// 고위 연금술사 제롬
		case 1181:				// 고위 마법술사 미엘
		case 1182:				// 제사장 미쿠
			{
				nObjectData = 1;
				if(opc && opc->m_pArea && df->m_pZone && df->m_pZone->m_index == ZONE_AKAN_TEMPLE)
				{
					{
						CNetMsg::SP rmsg(new CNetMsg);
						RaidSceneMsg(rmsg, OBJECT_TYPE_TODO, KILL_NPC, nAkanNpcIdx, nObjectData);
						do_ExRaidScene(opc, rmsg);
					}
				}
			}
			break;
		case 1259:	//망각의 신전
			{
				nObjectData = 1;
				if(opc && opc->m_pArea && df->m_pZone && df->m_pZone->m_index == ZONE_DUNGEON4)
				{
					CNetMsg::SP rmsg(new CNetMsg);
					RaidSceneMsg(rmsg, OBJECT_TYPE_TODO, KILL_NPC, nAkanNpcIdx, nObjectData);
					do_ExRaidScene(opc, rmsg);
				}
			}
			break;
		case 1364:
			{
				if(opc && opc->m_pArea && df->m_pZone && df->m_pZone->m_index == ZONE_TARIAN_DUNGEON)
				{
					CNetMsg::SP rmsg(new CNetMsg);
					RaidSceneMsg(rmsg, OBJECT_TYPE_TODO, KILL_NPC, nAkanNpcIdx, 1);
					do_ExRaidScene(opc, rmsg);
				}
			}
			break;
		default:
			break;
		}

#ifdef REFORM_PK_PENALTY_201108 // PK 패널티 리폼 :: npc를 잡으면 무조건 헌터 쪽으로 향상 시켜준다.
		if( !gserver->m_bNonPK )
		{
			if(df && opc)
			{
				int nlevel = df->m_level - opc->m_level;
				int pkPenalty = 0;
				if( nlevel > 4 )
					pkPenalty += 15;
				else if( nlevel > -5 )
					pkPenalty += 10;
				else if( nlevel <= -5 && nlevel >= -10)
					pkPenalty += 5;

				// 성향 수치 상승 증폭제를 사용 중이라면
				if( opc->m_assist.m_avRate.pkDispositionPointValue > 0 )
				{
					pkPenalty = pkPenalty * opc->m_assist.m_avRate.pkDispositionPointValue;
					opc->m_assist.CureByItemIndex(7474);	// 성향 수치 상승 증폭제
					opc->m_assist.CureByItemIndex(7475);	// 성향 수치 상승 증폭제
					opc->m_assist.CureByItemIndex(7476);	// 성향 수치 상승 증폭제
				}
				opc->AddPkPenalty( pkPenalty );

				{
					CNetMsg::SP rmsg(new CNetMsg);
					CharStatusMsg(rmsg, opc, 0);
					opc->m_pArea->SendToCell(rmsg, opc, false);
				}

				opc->m_bChangeStatus = true;
			}
		}
#else // REFORM_PK_PENALTY_201108 // PK 패널티 리폼
		if (opc && opc->IsChaotic() && df->m_level >= opc->m_level - 5)
		{
			opc->m_pkRecoverNPCCount++;
			if (opc->m_pkRecoverNPCCount >= 25)
			{
				opc->m_pkRecoverNPCCount = 0;

				if( !gserver->m_bNonPK )
					opc->m_pkPenalty++;

				{
					CNetMsg::SP rmsg(new CNetMsg);
					CharStatusMsg(rmsg, opc, 0);
					opc->m_pArea->SendToCell(rmsg, opc, false);
				}

				opc->m_bChangeStatus = true;
			}
		} // 카오 성향 회복
#endif // REFORM_PK_PENALTY_201108 // PK 패널티 리폼
		// Exp, SP 분배
		// 이루틴중 레벨업을 하여 존이동을 하였을 경우 나머지 실행하지 않는다.
		if( DivisionExpSP(df, tpc, nTotalDamage) )
			goto END_PROC;

		// 아이템 드롭
		ProcDropItemAfterBattle(df, opc, tpc, level);

		// 진행중인 Quest 중 죽은 npc로 진행중이면 UpdateData
		if (opc && opc == tpc)
		{
			if( opc->m_pZone->IsPersonalDungeon() )
			{
				opc->m_pArea->m_nMakeNPC++;

#if defined ( LC_GAMIGO ) || defined ( LC_KOR ) || defined ( LC_USA )
				if( df->m_proto->m_index == 5 )
				{
					if(opc->m_pArea->m_nMakeNPC < 103)
						goto SKIP_DROP;
					else
					{
						GAMELOG << init("QUEST COMPLETE PD1", opc)
								<< opc->m_pArea->m_nMakeNPC
								<< end;
					}
				}
				else if(df->m_proto->m_index == 201 && opc->m_pArea->m_nMakeNPC < 50)
				{
					goto SKIP_DROP;
				}
#else
				if( (df->m_proto->m_index == 5 || df->m_proto->m_index == 201 ) && opc->m_pArea->m_nMakeNPC < 50 )
				{
					goto SKIP_DROP;
				}
#endif // LC_GAMIGO || LC_KOR || LC_USA
			}

#ifdef PARTY_QUEST_ITEM_BUG_
			ProcDeadQuestProc(opc, df, QTYPE_SCALE_PERSONAL); // 내가 어그로도 먹고 몬스터도 막타 쳤단다.
#else
			CQuest* pQuest = NULL;
			CQuest* pQuestNext = opc->m_questList.GetNextQuest(NULL, QUEST_STATE_RUN);
			while ((pQuest = pQuestNext))
			{
				pQuestNext = opc->m_questList.GetNextQuest(pQuestNext, QUEST_STATE_RUN);
				// 퀘스트 있고 수행중이고 반복, 수집, 격파, 구출 퀘스트이면
				switch (pQuest->GetQuestType0())
				{
				case QTYPE_KIND_REPEAT:
				case QTYPE_KIND_COLLECTION:
				case QTYPE_KIND_DEFEAT:
				case QTYPE_KIND_SAVE:
					pQuest->QuestUpdateDataForParty(opc, df);
					break;

				default:
					break;
				}
			}
			if( pQuest == NULL && opc->IsParty() && opc->m_party )
			{
				int i;
				const CPartyMember* pPartyMember;
				CPC*	pPartyPC;

				for(i=0; i<MAX_PARTY_MEMBER; ++i)
				{
					pPartyMember = opc->m_party->GetMemberByListIndex(i);
					if(pPartyMember && pPartyMember->GetMemberPCPtr())
					{
						pPartyPC = pPartyMember->GetMemberPCPtr();

						if(opc->m_pArea->FindCharInCell(opc, pPartyPC->m_index, MSG_CHAR_PC))
						{
							pQuest = pPartyPC->m_questList.FindQuestByMob( df->m_idNum);

							if( pQuest == NULL)
								continue;

							if( pQuest->GetPartyScale() != QTYPE_SCALE_PARTY)
								break;

							switch (pQuest->GetQuestType0())
							{
							case QTYPE_KIND_REPEAT:
							case QTYPE_KIND_COLLECTION:
							case QTYPE_KIND_DEFEAT:
							case QTYPE_KIND_SAVE:
								pQuest->QuestUpdateData(pPartyPC, df);
								break;

							default:
								break;
							}
						}
					}
				}
			}
#endif // PARTY_QUEST_ITEM_BUG_
		}
#ifdef PARTY_QUEST_ITEM_BUG_
		else if(opc) // [2010/12/28 derek] opc == NULL 인데도 들어가져서 퀘스트 찾다가 서버 다운되어 추가함.
		{
#ifdef _BATTLEGROUP_QUEST_BUG_PIX
			if( opc->IsExped() ) // 어글은 않먹었지만 막타로 잡았으면
				ProcDeadQuestProc(opc, df, QTYPE_SCALE_BATTLEGROUP);
			else
#endif
				ProcDeadQuestProc(opc, df, QTYPE_SCALE_PARTY);
		}

#endif //PARTY_QUEST_ITEM_BUG_
	} // 죽은 NPC가 공성탑이나 수호병이 아닐 경우 처리
	else
	{
		int level = -1;
		LONGLONG nTotalDamage = 0;
		// 우선권 PC, 평균 레벨 구하기
		CPC* tpc = FindPreferencePC(df, &level, &nTotalDamage);
		DropWarCastleToken(df, opc, tpc, level);
	}

SKIP_DROP:

	// 수호탑은 DelNPC() 안하고 UpdateGateState() 후에 메시지로 알린다.
	if (df->m_proto->CheckFlag(NPC_CASTLE_TOWER) != 0)
	{
		int gstate_old = 0, gstate_new = 0;

		CWarCastle * castle = CWarCastle::GetCastleObject(ZONE_MERAC);
		CDratanCastle * pCastle = CDratanCastle::CreateInstance();

		if (of->m_pZone->m_index == ZONE_MERAC)
		{
			if (castle != NULL)
			{
				gstate_old = castle->GetGateState();
				gstate_old |= pCastle->GetGateState();
				castle->UpdateGateState(df);
				gstate_new = castle->GetGateState();
				gstate_new |= pCastle->GetGateState();
			}
		}
		else if (of->m_pZone->m_index == ZONE_DRATAN)
		{
			gstate_old = pCastle->GetGateState();

			if (castle != NULL)
			{
				gstate_old |= castle->GetGateState();
			}

			pCastle->UpdateGateState(df);
			gstate_new = pCastle->GetGateState();

			if (castle != NULL)
			{
				gstate_new |= castle->GetGateState();
			}

			if (df->m_proto->CheckFlag(NPC_WARCASTLE) != 0)
			{
				// NPC_CASTLE_TOWER 에 NPC_WARCASTLE 면
				// 마스터 타워와 부활진지
				int qindex = df->m_proto->m_index;
				if (qindex >= 390 && qindex <= 396)
				{
					// 부활진지 파괴 알림
					CNetMsg::SP rmsg(new CNetMsg);
					CastleTowerQuartersCrushMsg(rmsg, qindex);
					of->m_pArea->SendToAllClient(rmsg);

					// 부활진지 파괴 처리
					/*pCastle->m_nRebrithGuild[df->m_proto->m_index - 390] =  -1;
					memset((void *)pCastle->m_strRebrithGuild[df->m_proto->m_index - 390], 0, 51);*/
				}
			}
		}

		if (gstate_old != gstate_new)
		{
			CNetMsg::SP rmsg(new CNetMsg);
			GuildWarGateStateMsg(rmsg, gstate_old, gstate_new);
			of->m_pArea->SendToAllClient(rmsg);
		}

		DelAttackList(df);

		if (of->m_pZone->m_index == ZONE_DRATAN)
		{
			if( df->m_proto->m_index == 351)
			{
				// 마스터 타워
				// 모든 타워 기능 정지
				pCastle->StopCastleTower();
			}
			else if (df->m_proto->CheckFlag(NPC_CASTLE_TOWER) != 0)
			{
				// 공격 수호상 (결계의 눈 등..) 로그
				GAMELOG << init("DRATAN CASTLE NPC DEAD : ") << df->m_proto->m_name
						<< " BROKEN BY : " << of->m_name << end;
				// 마스터 타워가 아닌 모든 타워
				int  i;
				// 부활 진지 삭제
//				for (i=0; i<7; i++)
//				{
//					if (pCastle->m_pRebrithNPC[i] == df)
//					{
//						pCastle->m_pRebrithNPC[i] = NULL;
//						pCastle->m_nRebrithGuild[i] = -1;
//						memset((void *)pCastle->m_strRebrithGuild[i], 0, 51);
//#ifdef BUGFIX_WARCASTLE_REGEN
//						pCastle->m_nRegenTimeRebirthNPC[i] = gserver->getNowSecond() + pCastle->GetRegenNPCRebirthTime();
//#else
//						pCastle->m_nRegenTimeRebirthNPC[i] = gserver->m_pulse + pCastle->GetRegenNPCRebirthTime();
//#endif // BUGFIX_WARCASTLE_REGEN
//					}
//				}

				// 워프 타워 삭제
				for (i=0; i<5; i++)
				{
					if (pCastle->m_pWarpNPC[i] == df)
					{
						pCastle->m_pWarpNPC[i] = NULL;
					}
				}

				// 결계의 눈 삭제
				for (i=0; i<5; i++)
				{
					if (pCastle->m_gateNPC[i] == df)
					{
						pCastle->m_gateNPC[i] = NULL;
					}
				}

				// 알림
				of->m_pArea->CharFromCell(df, true);
				of->m_pArea->DelNPC(df);
			}
		}
		return ;
	} // 수호탑은 DelNPC() 안하고 UpdateGateState() 후에 메시지로 알린다.
//#endif

#ifdef EXTREME_CUBE
	if(df->m_bCubeRegen)
	{
		CCubeSpace* cube = gserver->m_extremeCube.GetExtremeCube(df->m_pArea->m_index);
		if(cube)
		{
			cube->DelMob(df);

			if(gserver->m_extremeCube.IsGuildCubeTime() && opc && opc->m_guildInfo && opc->m_guildInfo->guild())
			{
				CCubeMemList* CubeMemList;
				CubeMemList = gserver->m_extremeCube.FindMemList(opc->m_guildInfo->guild());
				if(CubeMemList)
				{
					time_t lastCubePoint;

					time(&lastCubePoint);
					CNetMsg::SP rmsg(new CNetMsg);
					HelperAddCubePointMsg(rmsg, opc->m_guildInfo->guild()->index(), df->m_level, lastCubePoint);
					SEND_Q(rmsg, gserver->m_helper);
				}
			}
		}
	}

	if(df->m_pZone != NULL && df->m_proto->m_index == 529 && df->m_pZone->IsExtremeCube())
	{
		CCubeSpace* cube = gserver->m_extremeCube.GetExtremeCube(df->m_pArea->m_index);

		if(cube && (cube->m_crystal == df) )
		{
			// cube->m_crystal = NULL;

			cube->DelCrystal(false);
			cube->m_waitTime = gserver->m_pulse + PULSE_REAL_SEC * 10;
			return ;
		}
	}
	else if(df->m_pZone != NULL && df->m_proto->m_index == 527 && df->m_pZone->IsExtremeCube())
	{
		CCubeSpace* cube = gserver->m_extremeCube.GetExtremeCube(df->m_pArea->m_index);

		if(cube && (cube->m_crystal == df) )
		{
			// cube->m_crystal = NULL;

			cube->DelCrystal(false);
			cube->m_waitTime = gserver->m_pulse + PULSE_REAL_SEC * 10;
			return ;
		}
	}
#endif // EXTREME_CUBE

	if(df && opc)
	{
		vec_affinityList_t::iterator it = df->m_proto->m_affinityList.begin();
		vec_affinityList_t::iterator endit = df->m_proto->m_affinityList.end();
		
		int point = 0;

		for(; it != endit; ++it)
		{
			CAffinityProto* proto = *(it);

			CAffinity* affinity = opc->m_affinityList.FindAffinity(proto->m_index);
			if(affinity)
			{
				point = proto->GetAffinityPointOfNPC(df->m_idNum);
				int bonus = 0;
				if(opc->m_avPassiveAddition.affinity_monster > 0)
				{
					bonus += opc->m_avPassiveAddition.affinity_monster;
				}
				if(opc->m_avPassiveRate.affinity_monster > 0)
				{
					bonus = point * (opc->m_avPassiveRate.affinity_monster - 100) / SKILL_RATE_UNIT;
				}

				affinity->AddPoint( point, opc, bonus);
			}
		}
	}

	if(df->m_ctCount > 0)
	{
		gserver->m_npc_ctTime.erase(df->m_index);
	}

END_PROC:

	//rvr 존에서 공격시에 동작해야 되는 함수 (NPC 가 죽었을 경우)
	if(opc != NULL && of->m_pZone->isRVRZone() && df->m_pZone->isRVRZone())
	{
		ProcDead_RVR(opc, df);
	}

	// 모든 몬스터는 몬스터에게 죽으면 패스
	if ( onpc || bNPCKilledNPC )
	{
		// 해당 에어리어에 죽은 수를 표시한다.  여기서는 바로 안지우고 따로 처리..
		// MobActivity.cpp::MobActivity() 타고 들어오면 꼭 여길 거쳐야한다.
		onpc->m_pArea->m_nNPC_Killed_NPC++;
	}
	else
	{
		DelAttackList(df);
		of->m_pArea->CharFromCell(df, true);
		of->m_pArea->DelNPC(df);
	}
}