CNPC *CCenario::removeNPC(int idNPC) { CNPC *temp = (CNPC*)_jogadores->removePersonagem(idNPC); _contador->removeID(temp->getSceneID()); return(temp); //return((CNPC*)_npcs->removePersonagem(idNPC)); }
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; }
void CZone::removeNPC( CNPC *npcToDelete ) { for ( size_t curNPCNr=0; curNPCNr<npcs.size(); ++curNPCNr ) { CNPC *curNPC = npcs[ curNPCNr ]; if ( curNPC == npcToDelete ) { curNPC->markAsDeleted(); break; } } }
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; } } }
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 ); } } } }
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(); }
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 }
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 ); }
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); } }