bool CDropManager::dropItem(CPC* _pPC, CNPC* _pNPC, CDropItemData * _pDropItem, bool _bPreferenceIndex) { CItem* pItem = gserver->m_itemProtoList.CreateItem( _pDropItem->getIndex(), -1 , _pDropItem->getPlus(), _pDropItem->getFlag(), _pDropItem->getCount() ); if (!pItem) { GAMELOG << init("DROP_SYSTEM ITEM DROP FAILD", _pPC) << _pDropItem->getIndex() << delim << _pDropItem->getPlus() << delim << _pDropItem->getFlag() << delim << _pDropItem->getCount() << end; return false; } if( _bPreferenceIndex ) pItem->m_preferenceIndex = _pPC->m_index; if( _pDropItem && _pDropItem->getIndex() == NAS_ITEM_DB_INDEX) { //돈일 경우 돈 메시지 전송 GoldType_t moneyCount = _pDropItem->getCount(); _pPC->m_inventory.increaseMoney(moneyCount); GAMELOG << init("DROP_SYSTEM ITEM NAS INPUT SUCC", _pPC) << moneyCount << end; } else { CNetMsg::SP rmsg(new CNetMsg); _pNPC->m_pArea->DropItem(pItem, (CCharacter*)_pNPC); ItemDropMsg(rmsg, (CCharacter*)_pNPC, pItem); pItem->m_pArea->SendToCell(rmsg, GET_YLAYER(pItem), pItem->m_cellX, pItem->m_cellZ); GAMELOG << init("DROP_SYSTEM ITEM DROP SUCC", _pPC) << itemlog(pItem) << end; } return true; }
void do_GMItemDrop(CPC *a1, char *a2) { COptionProto *j; // [sp+4Ch] [bp-2Ch]@33 CItem *v28; // [sp+54h] [bp-24h]@15 int *v29; // [sp+58h] [bp-20h]@1 int *v30; // [sp+5Ch] [bp-1Ch]@1 int v31; // [sp+60h] [bp-18h]@1 long long v32; // [sp+64h] [bp-14h]@13 int v33; // [sp+6Ch] [bp-Ch]@10 int v34; // [sp+70h] [bp-8h]@7 int v35; // [sp+74h] [bp-4h]@4 char *v36; // [sp+84h] [bp+Ch]@4 char *v37; // [sp+84h] [bp+Ch]@7 char *v38; // [sp+84h] [bp+Ch]@10 char *v39; // [sp+84h] [bp+Ch]@13 char *v40; // [sp+84h] [bp+Ch]@18 char *v41; // [sp+84h] [bp+Ch]@25 v31 = 0; v30 = 0; v29 = 0; if(a2) { if(*a2) { v36 = AnyOneArg(a2, g_buf, 0); v35 = atoi(g_buf); if(v36) { if(*v36) { v37 = AnyOneArg(v36, g_buf, 0); v34 = atoi(g_buf); if(v37) { if(*v37) { v38 = AnyOneArg(v37, g_buf, 0); v33 = atoi(g_buf); if(v38) { if(*v38) { v39 = AnyOneArg(v38, g_buf, 0); v32 = atoll(g_buf); if(!v32) v32 = 1; v28 = a1->Unk412->DropItem(v35, a1, v34, v33, v32, 0); if(v28) { if(v39) { if(*v39) { v40 = AnyOneArg(v39, g_buf, 0); v31 = atoi(g_buf); if(v31 > 0 || v31 <= 5) { v30 = (int *)malloc(4 * v31); v29 = (int *)malloc(4 * v31); for(int i = 0; i < v31; ++i) { if(!v40 || !*v40 || (v41 = AnyOneArg(v40, g_buf, 0), v30[i] = atoi(g_buf), !v41) || !*v41) return; v40 = AnyOneArg(v41, g_buf, 0); v29[i] = atoi(g_buf); if(v30[i] >= 0 && v30[i] <= 35 && v29[i] > 0 && v29[i] <= 6) { j = gserver.Unk452236.FindProto(v30[i]); if(j) { v28->Unk68[i].Unk0 = j; v28->Unk68[i].Unk4 = v30[i]; v28->Unk68[i].Unk8 = v29[i]; v28->Unk68[i].Unk12 = j->Unk8[v29[i]-1]; v28->Unk68[i].SetDBValue(); ++v28->Unk168; } } } } } } CNetMsg v25; ItemDropMsg(v25, a1, v28); a1->Unk412->SendToCell(v25, a1, 1, 4); g_gamelogbuffer.__ls(init("ITEM_LOAD", a1->Unk8)); g_gamelogbuffer.__ls(v28->Unk28); g_gamelogbuffer.__ls(delim); g_gamelogbuffer.__ls(v28->Unk44); g_gamelogbuffer.__ls(delim); g_gamelogbuffer.__ls(v28->Unk36); g_gamelogbuffer.__ls(delim); g_gamelogbuffer.__ls(v28->Unk40); g_gamelogbuffer.__ls(delim); g_gamelogbuffer.__ls(v28->Count()); g_gamelogbuffer.__ls(delim); g_gamelogbuffer.__ls(v28->Unk168); for(int j_1 = 0; j_1 < v31; j_1++) { g_gamelogbuffer.__ls(delim); g_gamelogbuffer.__ls(v30[j_1]); g_gamelogbuffer.__ls(delim); g_gamelogbuffer.__ls(v29[j_1]); } g_gamelogbuffer.__ls(end); if(v30 && v30) delete v30; if(v29 && v29) delete v29; } } } } } } } } } }
void ProcDropItemAfterBattle(CNPC* df, CPC* opc, CPC* tpc, int level) { if(df->m_pZone->IsComboZone()) { DropComboGiftMob(df, opc, tpc, level); return ; } #ifdef SYSTEM_TREASURE_MAP if( df->m_idNum == TREASURE_BOX_NPC_INDEX ) // npc 일경우 보물 상자만 드랍 한다. { DropTreasureBoxNpc(df, opc, tpc, level); return; } // 보물 지도는 필드에서만 드랍된다. if( df->m_pZone->CheckTreasureDropFlag() && df->m_pZone->IsFieldZone() ) { DropTreasureMap(df, opc, tpc, level); } #endif // 아이템 드롭율 증폭제 검사 bool hcSepDrop = false; bool hcDropPlus_S360 = false; bool hcPlatinumDrop = false; if (opc && tpc == opc) { if (opc->m_assist.m_avAddition.hcSepDrop) { opc->m_assist.CureByItemIndex(884); // 아이템 hcSepDrop = true; CNetMsg::SP rmsg(new CNetMsg); EventErrorMsg(rmsg, MSG_EVENT_ERROR_SEPTEMBER_DROP); SEND_Q(rmsg, opc->m_desc); } if (opc->m_assist.m_avAddition.hcSepDrop_Cash) { opc->m_assist.CureByItemIndex(6096); // 아이템 hcSepDrop = true; CNetMsg::SP rmsg(new CNetMsg); EventErrorMsg(rmsg, MSG_EVENT_ERROR_SEPTEMBER_DROP); SEND_Q(rmsg, opc->m_desc); } // 추천서버포션 드롭율 상승 else if (opc->m_assist.m_avAddition.hcDropPlus_S360) { opc->m_assist.CureBySkillIndex(360); hcDropPlus_S360 = true; } else if(opc->m_assist.m_avAddition.hcPlatinumDrop) { opc->m_assist.CureByItemIndex(2855); // 아이템 hcPlatinumDrop = true; } } // 아이템 드롭율 증폭제 검사 // 아이템 드롭 int loopcount; bool IsNotDropInCube = true; #ifdef EXTREME_CUBE if(df->m_bCubeRegen) IsNotDropInCube = false; #endif // EXTREME_CUBE] int itemDropLoop = MAX_NPC_DROPITEM_LOOP; #ifdef EVENT_WORLDCUP_2010 if( df->m_proto->m_index == 1105 ) itemDropLoop = 1; #endif // #ifdef EVENT_WORLDCUP_2010 for (loopcount = 0; loopcount < itemDropLoop; loopcount++) { // 5레벨보다 크면 아이템 드롭 없음 // 1. 드롭할 수 있는 수 범위에서 아이템 선정 // 2. 그 아이팀의 드롭확률로 드롭여부 결정 // 3. 드롭 #ifdef EVENT_WORLDCUP_2010 // 트라이앵글 볼(1105) 일경우 무조건 아이템을 드랍 한다 if( ( df->m_proto->m_itemCount > 0 && ((level != -1 && level - df->m_level <= 5) || !IsNotDropInCube) ) || df->m_proto->m_index == 1105) #else if (df->m_proto->m_itemCount > 0 && ((level != -1 && level - df->m_level <= 5) || !IsNotDropInCube) ) #endif { CItem* dropItem = NULL; int tableindex; #ifdef EVENT_WORLDCUP_2010 if( df->m_proto->m_index == 1105 ) { // npc툴 드랍 테이블1,2번에 각각 축국공, 황금 축구공이 100%g확률로 들어가 있어야 한다. tableindex = GetRandom(1, 10000); // 0. 95%확률로 축구공. 1. 5% 확률 황금 축구공 2. 꽝 if( tableindex <= 9000 ) tableindex = 0; else if( tableindex <= 9500) tableindex = 1; else tableindex = 2; } else #endif tableindex = GetRandom(0, MAX_NPC_DROPITEM - 1); int dropprob = df->m_proto->m_itemPercent[tableindex]; dropprob = dropprob * gserver->m_itemDropProb / 100; if (tpc) { // 자두 if (tpc->m_assist.m_avAddition.hcDropPlus_838) dropprob *= 2; // 행운의스크롤, 5080강운의 스크롤과 변수를 같이 사용한다. if (tpc->m_assist.m_avAddition.hcScrollDrop) dropprob *= 2; if (tpc->m_assist.m_avAddition.hcScrollDrop_5081) dropprob *= 4; // 행운 주문서 if (tpc->m_assist.m_avAddition.hcDropPlus_2141) { if (GetRandom(1, 10000) <= 2000 ) // 20 % { dropprob *= 2; } } // 플래티늄 행운의 스크롤 if(tpc->m_assist.m_avAddition.hcPlatinumScroll) { dropprob *= 4; } } // BS 수정 : 아이템 드롭 이벤트 dropprob = dropprob * gserver->m_nItemDropEventRate / 100; // 드롭율 상승 %단위 누적 if (opc && tpc == opc && opc->m_assist.m_avAddition.hcDropPlusPer100 > 0) dropprob += dropprob * opc->m_assist.m_avAddition.hcDropPlusPer100 / 100; #ifdef DOUBLE_ITEM_DROP if ( gserver->m_bDoubleItemEvent ) dropprob += dropprob * gserver->m_bDoubleItemPercent / 100; #endif // DOUBLE_ITEM_DROP // 9월 이벤트 드롭율 10배 if (hcSepDrop) dropprob = dropprob * 10; // 추천서버포션 드롭율 상승 else if (hcDropPlus_S360) dropprob = dropprob * 10; else if (hcPlatinumDrop) dropprob = dropprob * 20; if( opc && opc->m_assist.m_avAddition.hcRandomDropUp > 0 && GetRandom(0,100) <= opc->m_assist.m_avAddition.hcRandomDropUp ) { dropprob = dropprob * 10; CNetMsg::SP rmsg(new CNetMsg); EffectEtcMsg(rmsg, opc, MSG_EFFECT_ETC_RANDOM_DROP); opc->m_pArea->SendToCell(rmsg, opc, true); } if( tpc ) { if( gserver->isActiveEvent( A_EVENT_XMAS) ) { if ( tpc->m_assist.m_avAddition.hcDropPlus_Xmas2007 > 0) dropprob += df->m_proto->m_itemPercent[tableindex] * tpc->m_assist.m_avAddition.hcDropPlus_Xmas2007; } } #ifdef IMP_SPEED_SERVER // Zone Drop 률 적용 if( gserver->m_bSpeedServer && tpc && tpc->m_pZone ) { dropprob = dropprob * tpc->m_pZone->GetZoneDrop() / 100; } #endif //IMP_SPEED_SERVER if (df->m_proto->m_item[tableindex] != -1 && GetRandom(1, 10000) <= dropprob) { if (df->m_proto->m_item[tableindex] == 84) { dropItem = df->m_pArea->DropItem(df->m_proto->m_item[tableindex], df, 0, df->m_level, 1); } #if defined (LC_USA) || defined(LC_BILA) // 대만과 말레이시아는 중소형 체력약이 소형으로 떨어진다 else if( df->m_proto->m_item[tableindex] == 44 || df->m_proto->m_item[tableindex] == 45 ) { dropItem = df->m_pArea->DropItem(43, df, 0, 0, 1); } // 대만과 말레이시아는 중형 마나 회복 물약이 드롭되지 않는다. else if ( df->m_proto->m_item[tableindex] == 485 ) { dropItem = NULL; } #endif // #if defined (LC_USA) || defined(LC_BILA) #if defined (LC_USA) || defined(LC_BILA) // 대형 힐링포션 제작서, 대형 마나, 중형 마나 메뉴얼 드롭 금지 else if ( df->m_proto->m_item[tableindex] == 1066 || df->m_proto->m_item[tableindex] == 1067 || df->m_proto->m_item[tableindex] == 1068 || df->m_proto->m_item[tableindex] == 489) { dropItem = NULL; } #endif // #if defined (LC_USA) || defined (LC_BILA) else { // 61레벨 무기류 및 65레벨 방어구 드롭 금지 제작서 드롭 금지 switch (df->m_proto->m_item[tableindex]) { case -1: // 지우지 말것 dropItem = NULL; break; default: { bool bAvailableDrop = true; if (bAvailableDrop) dropItem = df->m_pArea->DropItem(df->m_proto->m_item[tableindex], df, 0, 0, 1, true); else dropItem = NULL; } break; } // switch (df->m_proto->m_item[tableindex]) } } // if (df->m_proto->m_item[tableindex] != -1 && GetRandom(1, 10000) <= dropprob) if (dropItem) { // 050303 : bs : 몬스터에게서 plus 붙은 아이템 만들기 if (df->m_proto->m_minplus >= 0 && df->m_proto->m_maxplus >= df->m_proto->m_minplus && df->m_proto->m_probplus > 0 && dropItem->CanUpgrade()) { if (GetRandom(1, 10000) <= df->m_proto->m_probplus) { dropItem->setPlus(GetRandom(df->m_proto->m_minplus, df->m_proto->m_maxplus)); } } // Drop Msg 보내기 // 아이템 우선권 셋팅 (같은 데미지 고려, 선공 고려) if (tpc) dropItem->m_preferenceIndex = tpc->m_index; else dropItem->m_preferenceIndex = -1; { CNetMsg::SP rmsg(new CNetMsg); ItemDropMsg(rmsg, df, dropItem); df->m_pArea->SendToCell(rmsg, GET_YLAYER(dropItem), dropItem->m_cellX, dropItem->m_cellZ); } if (df->m_proto->CheckFlag(NPC_BOSS | NPC_MBOSS)) { GAMELOG << init("MOB DROP ITEM") << "NPC INDEX" << delim << df->m_proto->m_index << delim << "NPC NAME" << delim << df->m_name << delim << "ITEM" << delim << itemlog(dropItem) << end; } } } } // // 아이템 드롭 // opc 공격 캐릭터, tpc 우선권 캐릭터 int job = -1; if(tpc) job = (int)tpc->m_job; else if(opc) job = (int)opc->m_job; if(job >= 0 && job < JOBCOUNT) { if(level != -1 && level - df->m_level <= 5) { if(df->m_proto->m_jobdropitem[job] > 0 && df->m_proto->m_jobdropitemprob[job] > 0) { int dropprob = df->m_proto->m_jobdropitemprob[job]; if(GetRandom(1, 10000) <= dropprob) { CItem* dropItem = NULL; dropItem = gserver->m_itemProtoList.CreateItem(df->m_proto->m_jobdropitem[job], -1, 0, 0, 1); if(dropItem) { df->m_pArea->DropItem(dropItem, df); CNetMsg::SP rmsg(new CNetMsg); ItemDropMsg(rmsg, df, dropItem); df->m_pArea->SendToCell(rmsg, df, true); GAMELOG << init("MOB DROP ITEM") << "NPC INDEX" << delim << df->m_proto->m_index << delim << "NPC NAME" << delim << df->m_name << delim << "ITEM" << delim << itemlog(dropItem) << end; } } } } } // 이 아이템은 레벨제한 없이 무조건 떨어트린다. int loopi = 0; for(loopi = 0; loopi < MAX_NPC_DROPITEM; loopi++) { if(df->m_proto->m_dropallitem[loopi] < 1) continue ; int dropprob = df->m_proto->m_dropallitemprob[loopi]; if(GetRandom(1, 10000) <= dropprob) { CItem* pItem = NULL; pItem = gserver->m_itemProtoList.CreateItem(df->m_proto->m_dropallitem[loopi], -1, 0, 0, 1); if(pItem) { if (tpc) pItem->m_preferenceIndex = tpc->m_index; else pItem->m_preferenceIndex = -1; df->m_pArea->DropItem(pItem, df); CNetMsg::SP rmsg(new CNetMsg); ItemDropMsg(rmsg, df, pItem); df->m_pArea->SendToCell(rmsg, df, true); GAMELOG << init("MOB DROP ALL ITEM") << "NPC INDEX" << delim << df->m_proto->m_index << delim << "NPC NAME" << delim << df->m_name << delim << "ITEM" << delim << itemlog(pItem) << end; } } } // 보석 드롭 for (loopcount = 0; loopcount < MAX_NPC_DROPITEM_LOOP; loopcount++) { // 5레벨보다 크면 아이템 드롭 없음 // 1. 드롭할 수 있는 수 범위에서 아이템 선정 // 2. 그 아이팀의 드롭확률로 드롭여부 결정 // 3. 드롭 if (df->m_proto->m_jewelCount > 0 && ((level != -1 && level - df->m_level <= 5) || !IsNotDropInCube) ) { CItem* dropItem = NULL; int tableindex = GetRandom(0, MAX_NPC_DROPJEWEL - 1); int dropprob = df->m_proto->m_jewelPercent[tableindex]; if (df->m_proto->m_jewel[tableindex] != -1 && GetRandom(1, 10000) <= dropprob) { switch (df->m_proto->m_jewel[tableindex]) { case -1: // 지우지 말것 dropItem = NULL; break; default: { dropItem = df->m_pArea->DropItem(df->m_proto->m_jewel[tableindex], df, 0, 0, 1, true); } break; } } if (dropItem) { // Drop Msg 보내기 // 아이템 우선권 셋팅 (같은 데미지 고려, 선공 고려) if (tpc) dropItem->m_preferenceIndex = tpc->m_index; else dropItem->m_preferenceIndex = -1; { CNetMsg::SP rmsg(new CNetMsg); ItemDropMsg(rmsg, df, dropItem); df->m_pArea->SendToCell(rmsg, GET_YLAYER(dropItem), dropItem->m_cellX, dropItem->m_cellZ); } GAMELOG << init("JEWEL ITEM") << "NPC INDEX" << delim << df->m_proto->m_index << delim << "NPC NAME" << delim << df->m_name << delim << "ITEM" << delim << itemlog(dropItem) << end; } } } // 보석 드롭 // typedef void (*NPC_DROP_FUNCTION) (CNPC* npc, CPC* pc, CPC* tpc, int level); // pc, tpc는 NULL이 될 수 있다 NPC_DROP_FUNCTION fnNPCDrop[] = { DropBloodGem, // 블러드젬 드롭 : 대만 천하대란 DropLuckySpecialStone, // 행운의 제련석 드롭 : 대만 천하대란 DropSpecialRefineStone, // 고제 드롭 DropPersonalDungeon2Ticket, // 퍼스널던전 2 입장권 드롭 DropBoosterItem, // 부스터 DropPersonalDungeon3Ticket, // 퍼스널던전 3 입장권 드롭 DropPersonalDungeon4Ticket, // 퍼스널던전 4 입장권 드롭 DropPetEgg, // 애완동물 알 드롭 DropNewMoonStoneItem, #ifdef EVENT_VALENTINE DropValentineItem, // 발렌타인 #endif #ifdef EVENT_WHITEDAY DropWhiteDayItem, // 화이트데이 #endif #ifdef DROP_MAKE_DOCUMENT DropMakeDocument, // 제작문서 드롭 #endif // DROP_MAKE_DOCUMENT DropRecommendItem, // 추천 서버 전용 인스턴스 포션 아이템 DropGoldenBallItem, // 골든볼 이벤트 RegenBlessWarrior, // 전사의 축복 DropHalloween2006Item, // 2006 할로윈 이벤트 DropRaidMonsterItem, DropMobScrollSpecialStone, DropEventGomdori2007, DropEventIndependenceDay2007USA, DropEventAprilFoolEvent, #ifdef EVENT_DROPITEM DropEventNpcDropItem, #endif // EVENT_DROPITEM DropAPetLifeBook, DropPhoenix_MembersTicket, DropTriggerItem, #ifdef LACARETTE_SYSTEM DropLacaRette, #endif DropHolyWater, DropWorldCupEvent, DropHalloween2014Event, DropArtifactItem, #ifdef DEV_EVENT_AUTO DropEventItem, #endif // DEV_EVENT_AUTO }; // 드롭 함수 테이블 // 방어코드 : tpc가 있는데 m_pZone이나 m_pArea가 없으면 NULL로 바꾼다 if (tpc && (tpc->m_pZone == NULL || tpc->m_pArea == NULL)) tpc = NULL; unsigned int fnDropLoop; for (fnDropLoop = 0; fnDropLoop < sizeof(fnNPCDrop) / sizeof(NPC_DROP_FUNCTION); fnDropLoop++) (fnNPCDrop[fnDropLoop])(df, opc, tpc, level); gserver->doEventDropItem(df, opc, tpc); // 돈 떨어뜨릴 확률 : default 80 % // BS 수정 : 낮은 레벨 몬스터 잡을때 패널티만 존재 // 잠수함 : 돈 드롭확률 int moneyDropProb = MONEY_DROP_PROB * gserver->m_moneyDropProb / 100; if (level != -1 && df->m_level - level < 0) moneyDropProb += (df->m_level - level) * 500; bool hcSepNas = false; if (opc && tpc == opc) { if (opc->m_assist.m_avAddition.hcSepNas) { opc->m_assist.CureByItemIndex(885); // 나스 hcSepNas = true; CNetMsg::SP rmsg(new CNetMsg); EventErrorMsg(rmsg, MSG_EVENT_ERROR_SEPTEMBER_NAS); SEND_Q(rmsg, opc->m_desc); } } // 돈 드롭 //CItem* money = NULL; if (GetRandom(1, 10000) <= moneyDropProb) // 80% { // 돈 액수 : +- 50% if(!df) { //잘못된 위치에서 몬스터를 잡았을 경우 GAMELOG << "NOT FOUND TARGET....." << df->m_idNum << end; return ; } GoldType_t count = df->m_proto->m_price * GetRandom(50, 150) / 100; #ifdef LC_RUS // 러시아는 망각의 신전을 제외한 지역에서 65 레벨 이상의 몬스터가 떨구는 나스는 40% 로 줄인다. if (df->m_pZone && df->m_pZone->m_index != ZONE_DUNGEON4 && df->m_level >= 65) count = count / 5 * 2; #endif // LC_RUS // 더블이벤트 if (gserver->m_bDoubleEvent) { #ifdef NEW_DOUBLE_GM_ZONE if( gserver->m_bDoubleEventZone == -1 || gserver->m_bDoubleEventZone == df->m_pZone->m_index ) #endif // NEW_DOUBLE_GM_ZONE count = count * gserver->m_bDoubleNasPercent / 100 ; } // 9월 이벤트 나스 10배 if (hcSepNas) count = count * 10; // 행운 주문서 if (tpc && tpc->m_assist.m_avAddition.hcDropPlus_2141) { if (GetRandom(1, 10000) <= 8000 ) // 80 % { count *= 2; } } //#endif // CAHNCE_EVENT if( opc && opc->m_pZone->m_index == ZONE_DRATAN_CASTLE_DUNGEON ) { CDratanCastle * pCastle = CDratanCastle::CreateInstance(); if( opc->m_guildInfo && opc->m_guildInfo->guild()->index() == pCastle->GetOwnerGuildIndex() ) { // 세금 없음 } else { GoldType_t tax=0; tax = count * pCastle->m_dvd.GetHuntRate() / 100; count = count - tax; gserver->AddTaxItemDratan( tax ); } } if( tpc == NULL ) { GAMELOG << "NOT FOUND TARGET....." << end; return; } //파티이면서 타입이 균등일때 if (tpc->IsParty() && (tpc->m_party->GetPartyType(MSG_DIVITYPE_MONEY) == MSG_PARTY_TYPE_RANDOM || tpc->m_party->GetPartyType(MSG_DIVITYPE_MONEY) == MSG_PARTY_TYPE_BATTLE) ) { DivisionPartyMoney(tpc, count); } //원정대이면서 타입이 균등일때 else if ( tpc->IsExped() && (tpc->m_Exped->GetExpedType(MSG_DIVITYPE_MONEY) == MSG_EXPED_TYPE_RANDOM || tpc->m_Exped->GetExpedType(MSG_DIVITYPE_MONEY) == MSG_EXPED_TYPE_BATTLE) ) { DivisionExpedMoney(tpc, count); } //이도 저도 아닐때 (개인 플레이할때) else { int bonus = 0; if(tpc->m_avPassiveAddition.money_nas > 0) { bonus += tpc->m_avPassiveAddition.money_nas; } if(tpc->m_avPassiveRate.money_nas > 0) { bonus = count * (tpc->m_avPassiveRate.money_nas - 100) / SKILL_RATE_UNIT; } count = count + count * tpc->m_artiGold / 100; tpc->m_inventory.increaseMoney(count, bonus); } if (df->m_proto->CheckFlag(NPC_BOSS | NPC_MBOSS)) { GAMELOG << init("MOB DROP MONEY") << "NPC INDEX" << delim << df->m_proto->m_index << delim << "NPC NAME" << delim << df->m_name << delim << "MONEY(NAS)" << delim << count << end; } } }
void ProcRVR(CPC* df, CCharacter* of) { CPC* oPC; CNPC* oNPC; if(IS_PC(of)) { oPC = TO_PC(of); if (!df->isSyndicate() && !oPC->isSyndicate()) { return; } if (df->isSyndicate() && !oPC->isSyndicate()) { LONGLONG point = 1; df->m_syndicateManager.decreaseSyndicatePoint(point); return; } if (!df->isSyndicate() && oPC->isSyndicate()) { LONGLONG point = 1; oPC->m_syndicateManager.increaseSyndicatePoint(point); return; } if (df->isSyndicate() && oPC->isSyndicate()) { LONGLONG dfPoint = 0; LONGLONG attPoint = 0; int itemIndex = 0; // int jewelKailuxPoint = SyndicateInfoDataManager::instance()->getJewelPoint(SYNDICATE::eSYNDICATE_KAILUX); int jewelDealerMoonPoint = SyndicateInfoDataManager::instance()->getJewelPoint(SYNDICATE::eSYNDICATE_DEALERMOON); // 카이룩스의 보석량이 딜라문보다 적다 if (jewelKailuxPoint < jewelDealerMoonPoint) { //공격자가 보석량이 작은 결사대 일 경우 if (oPC->getSyndicateType() == SYNDICATE::eSYNDICATE_KAILUX) { // 공격자의 보석량이 적고 공격자의 기여도가 높다 if (df->m_syndicateManager.getSyndicatePoint(df->getSyndicateType()) < oPC->m_syndicateManager.getSyndicatePoint(oPC->getSyndicateType())) { attPoint = 2; dfPoint = 5; itemIndex = 10129; } else if(df->m_syndicateManager.getSyndicatePoint(df->getSyndicateType()) == oPC->m_syndicateManager.getSyndicatePoint(oPC->getSyndicateType())) { // 공격자의 보석량이 적고 기여도가 같다 attPoint = 3; dfPoint = 3; itemIndex = 10130; } else { // 공격자의 보석량이 적고 기여도가 낮다 attPoint = 5; dfPoint = 2; itemIndex = 10130; } } //공격자가 보석량이 큰 결사대 일 경우 else if (oPC->getSyndicateType() == SYNDICATE::eSYNDICATE_DEALERMOON) { if (df->m_syndicateManager.getSyndicatePoint(df->getSyndicateType()) < oPC->m_syndicateManager.getSyndicatePoint(oPC->getSyndicateType())) { // 공격자의 보석량이 많고 기여도가 높다 attPoint = 1; dfPoint = 1; itemIndex = 10129; } else if(df->m_syndicateManager.getSyndicatePoint(df->getSyndicateType()) == oPC->m_syndicateManager.getSyndicatePoint(oPC->getSyndicateType())) { // 공격자의 보석략이 많고 기여도가 같다 attPoint = 1; dfPoint = 1; itemIndex = 10130; } else { // 공격자의 보석략이 많고 기여도가 작다 attPoint = 2; dfPoint = 1; itemIndex = 10130; } } } else { if (oPC->getSyndicateType() == SYNDICATE::eSYNDICATE_KAILUX) { // 공격자의 보석량이 많고 공격자의 기여도가 높다 // 사망자의 보석량이 적고 기여도가 작다 if (df->m_syndicateManager.getSyndicatePoint(df->getSyndicateType()) < oPC->m_syndicateManager.getSyndicatePoint(oPC->getSyndicateType())) { attPoint = 1; dfPoint = 1; itemIndex = 10129; } else if(df->m_syndicateManager.getSyndicatePoint(df->getSyndicateType()) == oPC->m_syndicateManager.getSyndicatePoint(oPC->getSyndicateType())) { // 공격자의 보석량이 많고고 기여도가 같다 attPoint = 1; dfPoint = 1; itemIndex = 10130; } else { // 공격자의 보석량이 많고 기여도가 낮다 attPoint = 2; dfPoint = 1; itemIndex = 10130; } } else if (oPC->getSyndicateType() == SYNDICATE::eSYNDICATE_DEALERMOON) { if (df->m_syndicateManager.getSyndicatePoint(df->getSyndicateType()) < oPC->m_syndicateManager.getSyndicatePoint(oPC->getSyndicateType())) { // 공격자의 보석량이 적고 기여도가 높다 attPoint = 2; dfPoint = 5; itemIndex = 10129; } else if(df->m_syndicateManager.getSyndicatePoint(df->getSyndicateType()) == oPC->m_syndicateManager.getSyndicatePoint(oPC->getSyndicateType())) { // 공격자의 보석량이 적고 기여도가 같다 attPoint = 3; dfPoint = 3; itemIndex = 10130; } else { // 공격자의 보석량이 적고 기여도가 작다 attPoint = 5; dfPoint = 2; itemIndex = 10130; } } } //기여도 수정 df->m_syndicateManager.decreaseSyndicatePoint(dfPoint); oPC->m_syndicateManager.increaseSyndicatePoint(attPoint); //창조의 보석 드랍 if(df->m_syndicateManager.isKing()) { itemIndex = 10131; } CItem* pItem = gserver->m_itemProtoList.CreateItem(itemIndex, -1, 0, 0, 1); pItem = df->m_pArea->DropItem(pItem, (CCharacter*)df); if(pItem && pItem->m_pArea) { pItem->m_preferenceIndex = oPC->m_index; CNetMsg::SP rmsg(new CNetMsg); ItemDropMsg(rmsg, df, pItem); pItem->m_pArea->SendToCell(rmsg, GET_YLAYER(pItem), pItem->m_cellX, pItem->m_cellZ); GAMELOG << init("Syndicate Jewel Drop.", df) << "ITEM" << delim << itemlog(pItem) << end; } switch(itemIndex) { case 10129: df->m_syndicateManager.syndicateDelJewel(1); break; case 10130: df->m_syndicateManager.syndicateDelJewel(5); break; case 10131: df->m_syndicateManager.syndicateDelJewel(30); break; } } // 로그 추가 oPC->m_syndicateManager.historyManager_.battleWinHistory(oPC->getSyndicateType(), df->getSyndicateType(), df->GetName()); df->m_syndicateManager.historyManager_.battleLoseHistory(df->getSyndicateType(), oPC->getSyndicateType(), oPC->GetName()); // 히스토리 전달 oPC->m_syndicateManager.historyManager_.sendHistory(oPC->getSyndicateType()); df->m_syndicateManager.historyManager_.sendHistory(df->getSyndicateType()); } else if(IS_NPC(of)) { oNPC = TO_NPC(of); int jewelKailuxPoint = SyndicateInfoDataManager::instance()->getJewelPoint(SYNDICATE::eSYNDICATE_KAILUX); int jewelDealerMoonPoint = SyndicateInfoDataManager::instance()->getJewelPoint(SYNDICATE::eSYNDICATE_DEALERMOON); if(jewelKailuxPoint > jewelDealerMoonPoint) { if(df->getSyndicateType() == SYNDICATE::eSYNDICATE_KAILUX) { df->m_syndicateManager.decreaseSyndicatePoint(2); } else { df->m_syndicateManager.decreaseSyndicatePoint(1); } } else { if(df->getSyndicateType() == SYNDICATE::eSYNDICATE_KAILUX) { df->m_syndicateManager.decreaseSyndicatePoint(1); } else { df->m_syndicateManager.decreaseSyndicatePoint(2); } } } }
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 }
bool local_exchangeWeapon(CPC* ch, CItem* item, bool bprolong, RequestClient::doItemUse* packet) { int extra1 = packet->extra_1; int extra2 = packet->extra_2; CItem* vitem = ch->m_inventory.FindByVirtualIndex(extra1); if (!vitem) return false; if (!vitem->IsWeaponType()) return false; if (vitem->m_itemProto->getItemSubTypeIdx() == extra2) return false; if (extra2 < 0 || extra2 >= 16) return false; int itemlevel = vitem->GetItemLevel(); // 레벨, 한손검, 석궁, 스태프, 대검, 도끼, 숏스테프, 활, 단검, -1, -1, -1, 이도류, 완드, 사이드, 폴암 : 할일 : 소서러 const static int matchTable[12][16] = { {1,48,530,600,12,558,356,50,528,-1,-1,-1,459,599,-1,-1}, {5,53,666,628,51,601,357,56,529,-1,-1,-1,610,619,-1,-1}, {9,55,637,629,52,602,358,57,532,-1,-1,-1,611,620,-1,-1}, {13,107,638,630,105,603,359,106,533,-1,-1,-1,612,621,-1,-1}, {17,180,639,631,306,604,360,185,534,-1,-1,-1,613,622,-1,-1}, {21,322,640,632,307,605,361,341,535,-1,-1,-1,614,623,-1,-1}, {25,323,641,633,308,606,362,342,536,-1,-1,-1,615,624,-1,-1}, {29,324,642,634,309,607,363,343,537,-1,-1,-1,616,625,983,995}, {33,325,643,635,310,608,364,344,538,-1,-1,-1,617,626,984,-996}, {37,326,644,636,311,609,365,345,539,-1,-1,-1,618,627,985,997}, {41,681,721,719,715,645,720,718,722,-1,-1,-1,716,717,986,998}, {45,800,823,816,793,794,815,808,822,-1,-1,-1,801,809,987,999} }; CItemProto* proto = NULL; int i; for (i = 0; i < 12; i++) { if (matchTable[i][0] == itemlevel) { proto = gserver->m_itemProtoList.FindIndex(matchTable[i][extra2 + 1]); break; } } if (proto == NULL) return false; CItem* newitem = gserver->m_itemProtoList.CreateItem(proto->getItemIndex(), -1, vitem->getPlus(), vitem->getFlag(), 1); if (!newitem) return false; GAMELOG << init("CASHITEM_CHANGE_WEAPON_WITHOUT OPTION", ch) << "OLD" << delim << itemlog(vitem) << delim; GAMELOG << "NEW" << delim << itemlog(newitem) << delim; ch->m_inventory.decreaseItemCount(vitem, 1); if (ch->m_inventory.addItem(newitem) == false) { ch->m_pArea->DropItem(newitem, ch); newitem->m_preferenceIndex = ch->m_index; CNetMsg::SP rmsg(new CNetMsg); ItemDropMsg(rmsg, ch, newitem); ch->m_pArea->SendToCell(rmsg, GET_YLAYER(newitem), newitem->m_cellX, newitem->m_cellZ); GAMELOG << "DROP" << end; } return true; }
// 펫 사망시 아이템 지급 bool DropPetItem(CPet* pet) { bool bRet = false; CPC* owner = pet->GetOwner(); if (owner) { const int nHorseDropList = 8; const int nDragonDropList = 12; int horseDropList[nHorseDropList][2] = { {886, 70}, // 말굽 {888, 30}, // 말의갈기 {889, 70}, // 말총 {890, 30}, // 말의등뼈 {891, 70}, // 말의어금니 {892, 70}, // 말의피 {893, 30}, // 말가죽 {894, 100} // 말의힘줄 }; int dragonDropList[nDragonDropList][2] = { {895, 45}, // 발톱 {896, 45}, // 날개 {897, 45}, // 송곳니 {898, 45}, // 눈알 {899, 45}, // 뿔 {900, 45}, // 힘줄 {901, 45}, // 가죽 {902, 45}, // 꼬리 {903, 45}, // 피 {904, 45}, // 심장 {905, 45}, // 루비 {906, 45}, // 등뼈 }; // 펫 종류에 따라 드롭 테이블 변경 bool bNoDrop = true; int i; int prob = GetRandom(1, 10000); int selIndex = 0; // 아이템 인덱스 int nStartIndex; int j; switch (pet->GetPetType()) { case PET_TYPE_HORSE: case PET_TYPE_BLUE_HORSE: case PET_TYPE_UNKOWN_HORSE: nStartIndex = GetRandom(0, nHorseDropList - 1); for (i = 0; i < nHorseDropList; i++) { j = (i + nStartIndex) % nHorseDropList; horseDropList[j][1] = horseDropList[j][1] * pet->m_level / 2; if (i > 0) { horseDropList[j][1] += horseDropList[(j + nHorseDropList - 1) % nHorseDropList][1]; } if (prob <= horseDropList[j][1]) { selIndex = horseDropList[j][0]; bNoDrop = false; break; } } break; case PET_TYPE_DRAGON: case PET_TYPE_PINK_DRAGON: case PET_TYPE_UNKOWN_DRAGON: nStartIndex = GetRandom(0, nDragonDropList - 1); for (i = 0; i < nDragonDropList; i++) { j = (i + nStartIndex) % nDragonDropList; dragonDropList[j][1] = dragonDropList[j][1] * pet->m_level / 2; if (i > 0) dragonDropList[j][1] += dragonDropList[(j + nDragonDropList - 1) % nDragonDropList][1]; if (prob <= dragonDropList[j][1]) { selIndex = dragonDropList[j][0]; bNoDrop = false; break; } } break; default: bNoDrop = true; } if (!bNoDrop) { CItem* dropItem = gserver->m_itemProtoList.CreateItem(selIndex, -1, 0, 0, 1); if (dropItem) { // TODO : petlog GAMELOG << init("PET ITEM CHANGE") << "PET" << delim << pet->GetPetTypeGrade() << delim << "INDEX" << delim << pet->m_index << delim << "LEVEL" << delim << pet->m_level << delim << "OWNER" << delim << owner->m_index << delim << owner->GetName() << delim << "ITEM" << delim << itemlog(dropItem, true) << delim; bool bDrop = false; if (owner->m_inventory.addItem(dropItem) == false) { owner->m_pArea->DropItem(dropItem, owner); dropItem->m_preferenceIndex = owner->m_index; CNetMsg::SP rmsg(new CNetMsg); ItemDropMsg(rmsg, owner, dropItem); owner->m_pArea->SendToCell(rmsg, GET_YLAYER(dropItem), dropItem->m_cellX, dropItem->m_cellZ); bDrop = true; } GAMELOG << ((bDrop) ? "DROP" : "GIVE") << end; bRet = true; } } } return bRet; }