////////////////////////////////////////////////////////////////////////////// // 슬레이어 오브젝트 핸들러 ////////////////////////////////////////////////////////////////////////////// void MoleShot::execute(Slayer* pSlayer, ObjectID_t TargetObjectID, SkillSlot* pSkillSlot, CEffectID_t CEffectID) throw(Error) { __BEGIN_TRY //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " Begin" << endl; Assert(pSlayer != NULL); Assert(pSkillSlot != NULL); try { Zone* pZone = pSlayer->getZone(); Assert(pZone != NULL); Creature* pTargetCreature = pZone->getCreature(TargetObjectID); //Assert(pTargetCreature != NULL); // NoSuch제거. by sigi. 2002.5.2 if (pTargetCreature==NULL) { executeSkillFailException(pSlayer, getSkillType()); return; } // 아이템이 없거나, 총 계열의 무기가 아니거나, SR이라면 // 이 기술을 사용할 수 없다. Item* pItem = pSlayer->getWearItem(Slayer::WEAR_RIGHTHAND); if (pItem == NULL || !isArmsWeapon(pItem)) // SR도 사용 가능하게 수정. by sigi. 2002.12.3 // || pItem->getItemClass() == Item::ITEM_CLASS_SR) { executeSkillFailException(pSlayer, getSkillType()); return; } Item::ItemClass IClass = pItem->getItemClass(); if (IClass == Item::ITEM_CLASS_SG) { SGexecute(pSlayer, pTargetCreature->getX(), pTargetCreature->getY(), pSkillSlot, CEffectID); } else if (IClass == Item::ITEM_CLASS_AR || IClass == Item::ITEM_CLASS_SMG // SR도 사용 가능하게 수정. by sigi. 2002.12.3 || IClass == Item::ITEM_CLASS_SR) { ARSMGexecute(pSlayer, pTargetCreature->getX(), pTargetCreature->getY(), pSkillSlot, CEffectID); } } catch (Throwable & t) { executeSkillFailException(pSlayer, getSkillType()); } //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl; __END_CATCH }
void EffectProtectionFromCurse::unaffect() throw(Error) { __BEGIN_TRY __BEGIN_DEBUG Creature* pCreature = dynamic_cast<Creature*>(m_pTarget); pCreature->removeFlag(Effect::EFFECT_CLASS_PROTECTION_FROM_CURSE); Resist_t resist = pCreature->getResist(MAGIC_DOMAIN_CURSE); resist = max(0,(int)(resist - m_Resist)); pCreature->setResist(MAGIC_DOMAIN_CURSE, resist); Zone* pZone = pCreature->getZone(); Assert(pZone != NULL); // 이펙트가 사라졌다고 알려준다. GCRemoveEffect gcRemoveEffect; gcRemoveEffect.setObjectID(pCreature->getObjectID()); gcRemoveEffect.addEffectList(Effect::EFFECT_CLASS_PROTECTION_FROM_CURSE); pZone->broadcastPacket(pCreature->getX(), pCreature->getY(), &gcRemoveEffect); __END_DEBUG __END_CATCH }
////////////////////////////////////////////////////////////////////////////// // 뱀파이어 오브젝트 핸들러 ////////////////////////////////////////////////////////////////////////////// void DestructionSpear::execute(Ousters* pOusters, ObjectID_t TargetObjectID, OustersSkillSlot* pOustersSkillSlot, CEffectID_t CEffectID) throw(Error) { __BEGIN_TRY Assert(pOusters != NULL); Assert(pOustersSkillSlot != NULL); try { Zone* pZone = pOusters->getZone(); Assert(pZone != NULL); Creature* pTargetCreature = pZone->getCreature(TargetObjectID); //Assert(pTargetCreature != NULL); // NoSuch제거. by sigi. 2002.5.2 if (pTargetCreature==NULL) { executeSkillFailException(pOusters, getSkillType()); return; } execute(pOusters, pTargetCreature->getX(), pTargetCreature->getY(), pOustersSkillSlot, CEffectID); } catch (Throwable & t) { executeSkillFailException(pOusters, getSkillType()); //cout << t.toString() << endl; } __END_CATCH }
void Session::assignCreaturesToGenerators() { if( !getMap()->isHeightMapEnabled() ) return; // find the creatures not assigned to a generator std::vector<Creature*> c; for( unsigned int i = 0; i < creatures.size(); i++ ) { Creature *creature = creatures[i]; if( creature->isMonster() && !creature->getStateMod( StateMod::dead ) ) { bool found = false; for( unsigned int t = 0; !found && t < generators.size(); t++ ) { CreatureGenerator *generator = generators[t]; for( unsigned int r = 0; !found && r < generator->creatures.size(); r++ ) { if( creature == generator->creatures[r] ) { found = true; } } } if( !found ) { c.push_back( creature ); } } } //cerr << "assigning " << c.size() << " creatures to " << generators.size() << " generators..." << endl; // remove the dead creatures from each generator (maybe there can't be any dead creatures at this point?) for( unsigned int t = 0; t < generators.size(); t++ ) { CreatureGenerator *generator = generators[t]; //cerr << "\tgenerator at " << generator->x << "," << generator->y << " count=" << generator->count << endl; generator->removeDead(); } // assign creatures to closest generator for( unsigned int i = 0; i < c.size(); i++ ) { Creature *creature = c[i]; CreatureGenerator *closest = NULL; float dist = 0; for( unsigned int t = 0; t < generators.size(); t++ ) { CreatureGenerator *generator = generators[t]; if( generator->count - generator->creatures.size() > 0 ) { float d = Constants::distance( creature->getX(), creature->getY(), creature->getShape()->getWidth(), creature->getShape()->getDepth(), generator->x, generator->y, 1, 1 ); if( closest == NULL || d < dist ) { closest = generator; dist = d; } } } if( closest ) { //cerr << "\t\tadding " << creature->getType() << " at " << creature->getX() << "," << creature->getY() << // " to generator at " << closest->x << "," << closest->y << endl; closest->creatures.push_back( creature ); } else { //cerr << "\t\tno generators w/o creatures were found." << endl; break; } } }
void ScourgeView::centerOnMonsterInTB() { scourge->getMap()->setMapCenterCreature( NULL ); if ( scourge->inTurnBasedCombat() ) { Battle *battle = scourge->getCurrentBattle(); Creature *c = battle->getCreature(); if ( !c->isPartyMember() || c->getStateMod( StateMod::possessed ) ) { scourge->getMap()->setMapCenterCreature( c ); scourge->getMap()->center( toint( c->getX() ), toint( c->getY() ), true ); } } }
void CGAbsorbSoulHandler::execute (CGAbsorbSoul* pPacket , Player* pPlayer) throw(Error) { __BEGIN_TRY __BEGIN_DEBUG_EX __BEGIN_DEBUG #ifdef __GAME_SERVER__ Assert(pPacket != NULL); Assert(pPlayer != NULL); try { GamePlayer* pGamePlayer = dynamic_cast<GamePlayer*>(pPlayer); Assert(pGamePlayer != NULL); if (pGamePlayer->getPlayerStatus() == GPS_NORMAL) { Creature* pCreature = pGamePlayer->getCreature(); Assert(pCreature != NULL); // 아우스터즈가 아닌 놈이 흡영을 할 수는 없다. if (!pCreature->isOusters()) return; Ousters* pOusters = dynamic_cast<Ousters*>(pCreature); // 완전 안전지대라면 기술 사용 불가. by sigi. 2002.11.14 ZoneLevel_t ZoneLevel = pCreature->getZone()->getZoneLevel(pCreature->getX(), pCreature->getY()); if ((ZoneLevel & COMPLETE_SAFE_ZONE) || (!isAbleToUseObjectSkill(pOusters, SKILL_ABSORB_SOUL))) { GCSkillFailed1 gcSkillFailed1; gcSkillFailed1.setSkillType(SKILL_ABSORB_SOUL); pPlayer->sendPacket(&gcSkillFailed1); return; } SkillHandler* pSkillHandler = g_pSkillHandlerManager->getSkillHandler(SKILL_ABSORB_SOUL); Assert(pSkillHandler != NULL); pSkillHandler->execute(pOusters, pPacket->getObjectID(), pPacket->getTargetZoneX(), pPacket->getTargetZoneY(), pPacket->getInvenObjectID(), pPacket->getInvenX(), pPacket->getInvenY(), pPacket->getTargetInvenX(), pPacket->getTargetInvenY()); } } catch (Throwable & t) { //cout << t.toString(); } #endif __END_DEBUG __END_DEBUG_EX __END_CATCH }
void EffectDestinies::affect() throw(Error) { __BEGIN_TRY setDeadline(0); Creature* pCaster = dynamic_cast<Creature*>(m_pTarget); int cx = pCaster->getX(); int cy = pCaster->getY(); Zone* pZone = pCaster->getZone(); for (int i=-8; i<=8; ++i ) for (int j=-8; j<=8; ++j ) { int tx = cx + i; int ty = cy + j; if (tx < 0 || ty < 0 ) continue; if (!isValidZoneCoord(pZone, tx, ty ) ) continue; list<Object*>& olist = pZone->getTile(tx, ty).getObjectList(); list<Object*>::iterator itr = olist.begin(); for (; itr != olist.end() ; ++itr ) { Object* pObject = *itr; if (pObject == NULL || pObject->getObjectClass() != Object::OBJECT_CLASS_CREATURE ) continue; Creature* pCreature = dynamic_cast<Creature*>(pObject); if (pCreature == NULL ) continue; bool isTarget = false; if (pCreature->getCreatureClass() == m_TargetClass ) { isTarget = true; if (m_TargetClass == Creature::CREATURE_CLASS_MONSTER ) { Monster* pTargetMonster = dynamic_cast<Monster*>(pCreature); if (pTargetMonster->getSpriteType() != m_TargetSpriteType ) isTarget = false; } } if (isTarget ) affect(pCreature); } } //cout << "EffectDestinies" << "affect BEGIN" << endl; __END_CATCH }
////////////////////////////////////////////////////////////////////////////// // 아우스터즈 오브젝트 핸들러 ////////////////////////////////////////////////////////////////////////////// void SummonGroundElemental::execute(Ousters* pOusters, ObjectID_t TargetObjectID, OustersSkillSlot* pOustersSkillSlot, CEffectID_t CEffectID) throw(Error) { __BEGIN_TRY //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << "begin " << endl; Assert(pOusters != NULL); Assert(pOustersSkillSlot != NULL); BYTE Grade = 0; if (pOustersSkillSlot->getExpLevel() <= 10 ) Grade = 0; else if (pOustersSkillSlot->getExpLevel() <= 20 ) Grade = 1; else if (pOustersSkillSlot->getExpLevel() < 30 ) Grade = 2; else Grade = 3; try { Zone* pZone = pOusters->getZone(); Assert(pZone != NULL); Creature* pTargetCreature = pZone->getCreature(TargetObjectID); //Assert(pTargetCreature != NULL); // NPC는 공격할 수가 없다. if (pTargetCreature==NULL // NoSuch제거 때문에.. by sigi. 2002.5.2 || pTargetCreature->isNPC()) { executeSkillFailException(pOusters, getSkillType(), Grade); //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " end " << endl; return; } execute(pOusters, pTargetCreature->getX(), pTargetCreature->getY(), pOustersSkillSlot, CEffectID); } catch (Throwable & t) { executeSkillFailException(pOusters, getSkillType(), Grade); //cout << t.toString() << endl; } //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " end " << endl; __END_CATCH }
////////////////////////////////////////////////////////////////////////////// // 슬레이어 오브젝트 핸들러 ////////////////////////////////////////////////////////////////////////////// void SwordRay::execute(Slayer* pSlayer, ObjectID_t TargetObjectID, SkillSlot* pSkillSlot, CEffectID_t CEffectID) throw(Error) { __BEGIN_TRY //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << "begin " << endl; // Slayer Object Assertion Assert(pSlayer != NULL); Assert(pSkillSlot != NULL); try { Zone* pZone = pSlayer->getZone(); Assert(pZone != NULL); Creature* pTargetCreature = pZone->getCreature(TargetObjectID); //Assert(pTargetCreature != NULL); // NoSuch제거. by sigi. 2002.5.2 if (pTargetCreature==NULL || !canAttack(pSlayer, pTargetCreature ) || pTargetCreature->isNPC()) { executeSkillFailException(pSlayer, getSkillType()); return; } execute(pSlayer, pTargetCreature->getX(), pTargetCreature->getY(), pSkillSlot, CEffectID); } catch (Throwable & t) { executeSkillFailException(pSlayer, getSkillType()); //cout << t.toString() << endl; } //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " end " << endl; __END_CATCH }
////////////////////////////////////////////////////////////////////////////// // 뱀파이어 오브젝트 핸들러 ////////////////////////////////////////////////////////////////////////////// void RefusalEther::execute(Ousters* pOusters, ObjectID_t TargetObjectID, OustersSkillSlot* pOustersSkillSlot, CEffectID_t CEffectID) throw(Error) { __BEGIN_TRY //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " Begin" << endl; Assert(pOusters != NULL); Assert(pOustersSkillSlot != NULL); BYTE Grade = 0; if (pOustersSkillSlot->getExpLevel() < 15 ) Grade = 0; else if (pOustersSkillSlot->getExpLevel() < 30 ) Grade = 1; else Grade = 2; try { Zone* pZone = pOusters->getZone(); Assert(pZone != NULL); Creature* pTargetCreature = pZone->getCreature(TargetObjectID); //Assert(pTargetCreature != NULL); // NoSuch제거. by sigi. 2002.5.2 if (pTargetCreature==NULL) { executeSkillFailException(pOusters, getSkillType(), Grade); return; } execute(pOusters, pTargetCreature->getX(), pTargetCreature->getY(), pOustersSkillSlot, CEffectID); } catch (Throwable & t) { executeSkillFailException(pOusters, getSkillType(), Grade); } //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl; __END_CATCH }
void SwordOfThor::execute(Slayer* pSlayer, ObjectID_t targetObjectID, SkillSlot* pSkillSlot, CEffectID_t CEffectID) throw(Error) { __BEGIN_TRY Zone* pZone = pSlayer->getZone(); Assert(pZone != NULL); Creature* pTargetCreature = pZone->getCreature(targetObjectID); //Assert(pTargetCreature != NULL); // NoSuch제거. by sigi. 2002.5.2 if (pTargetCreature==NULL) { executeSkillFailException(pSlayer, getSkillType()); return; } execute(pSlayer, pTargetCreature->getX(), pTargetCreature->getY(), pSkillSlot, CEffectID); __END_CATCH }
////////////////////////////////////////////////////////////////////////////// // 뱀파이어 오브젝트 핸들러 ////////////////////////////////////////////////////////////////////////////// void MeteorStrike::execute(Vampire* pVampire, ObjectID_t TargetObjectID, VampireSkillSlot* pVampireSkillSlot, CEffectID_t CEffectID) throw(Error) { __BEGIN_TRY //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << "begin " << endl; Assert(pVampire != NULL); Assert(pVampireSkillSlot != NULL); try { Zone* pZone = pVampire->getZone(); Assert(pZone != NULL); Creature* pTargetCreature = pZone->getCreature(TargetObjectID); //Assert(pTargetCreature != NULL); // NPC는 공격할 수가 없다. if (pTargetCreature==NULL // NoSuch제거 때문에.. by sigi. 2002.5.2 || !canAttack(pVampire, pTargetCreature ) || pTargetCreature->isNPC()) { executeSkillFailException(pVampire, getSkillType()); //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " end " << endl; return; } execute(pVampire, pTargetCreature->getX(), pTargetCreature->getY(), pVampireSkillSlot, CEffectID); } catch (Throwable & t) { executeSkillFailException(pVampire, getSkillType()); //cout << t.toString() << endl; } //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " end " << endl; __END_CATCH }
////////////////////////////////////////////////////////////////////////////// // 슬레이어 오브젝트 핸들러 ////////////////////////////////////////////////////////////////////////////// void ThunderStorm::execute(Slayer * pSlayer, ObjectID_t TargetObjectID, SkillSlot * pSkillSlot, CEffectID_t CEffectID) throw(Error) { __BEGIN_TRY Zone* pZone = pSlayer->getZone(); Assert(pZone!=NULL); Creature* pTargetCreature = pZone->getCreature(TargetObjectID); if (pTargetCreature!=NULL) { execute(pSlayer, pTargetCreature->getX(), pTargetCreature->getY(), pSkillSlot, CEffectID); } else { executeSkillFailException(pSlayer, getSkillType()); } __END_CATCH }
void EffectPlasmaRocketLauncher::unaffect() throw(Error) { __BEGIN_TRY Creature* pCreature = dynamic_cast<Creature*>(m_pTarget); // unaffect(pCreature); if (pCreature == NULL ) return; pCreature->removeFlag(Effect::EFFECT_CLASS_PLASMA_ROCKET_LAUNCHER); Zone* pZone = pCreature->getZone(); Assert(pZone != NULL); GCRemoveEffect gcRemoveEffect; gcRemoveEffect.setObjectID(pCreature->getObjectID()); gcRemoveEffect.addEffectList(Effect::EFFECT_CLASS_PLASMA_ROCKET_LAUNCHER); pZone->broadcastPacket(pCreature->getX(), pCreature->getY(), &gcRemoveEffect); __END_CATCH }
void EffectTrying::unaffect() throw(Error) { __BEGIN_TRY /* GCDeleteEffectFromTile gcDeleteEffect; gcDeleteEffect.setEffectID(getSendEffectClass()); gcDeleteEffect.setObjectID(getObjectID()); gcDeleteEffect.setXY(m_X, m_Y); m_pZone->broadcastPacket(m_X, m_Y, &gcDeleteEffect);*/ Creature* pCreature = dynamic_cast<Creature*>(m_pTarget); Assert(pCreature != NULL); GCRemoveEffect gcRemoveEffect; gcRemoveEffect.addEffectList(getSendEffectClass()); gcRemoveEffect.setObjectID(pCreature->getObjectID()); pCreature->getZone()->broadcastPacket(pCreature->getX(), pCreature->getY(), &gcRemoveEffect); __END_CATCH }
////////////////////////////////////////////////////////////////////////////// // 뱀파이어 오브젝트 핸들러 ////////////////////////////////////////////////////////////////////////////// void IceField::execute(Ousters* pOusters, ObjectID_t TargetObjectID, OustersSkillSlot* pOustersSkillSlot, CEffectID_t CEffectID) throw(Error) { __BEGIN_TRY //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " Begin" << endl; Assert(pOusters != NULL); Assert(pOustersSkillSlot != NULL); try { Zone* pZone = pOusters->getZone(); Assert(pZone != NULL); Creature* pTargetCreature = pZone->getCreature(TargetObjectID); //Assert(pTargetCreature != NULL); // NoSuch제거. by sigi. 2002.5.2 if (pTargetCreature==NULL || !canAttack(pOusters, pTargetCreature ) ) { executeSkillFailException(pOusters, getSkillType()); return; } execute(pOusters, pTargetCreature->getX(), pTargetCreature->getY(), pOustersSkillSlot, CEffectID); } catch (Throwable & t) { executeSkillFailException(pOusters, getSkillType()); } //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl; __END_CATCH }
void ScourgeView::drawCreatureInfos() { // creatures first for ( int i = 0; i < scourge->getSession()->getCreatureCount(); i++ ) { //if(!session->getCreature(i)->getStateMod(Constants::dead) && Creature *creature = scourge->getSession()->getCreature( i ); if ( scourge->getMap()->isLocationVisible( toint( creature->getX() ), toint( creature->getY() ) ) && scourge->getMap()->isLocationInLight( toint( creature->getX() ), toint( creature->getY() ), creature->getShape() ) && scourge->getSession()->isVisible( creature ) ) { showCreatureInfo( scourge->getSession()->getCreature( i ), false, false, false, ( scourge->getSession()->getCreature( i )->getCharacter() ? true : false ) ); } } // party next so red target circle shows over gray for ( int i = 0; i < scourge->getParty()->getPartySize(); i++ ) { bool player = scourge->getParty()->getPlayer() == scourge->getParty()->getParty( i ); if ( scourge->inTurnBasedCombat() && scourge->getParty()->isRealTimeMode() ) { player = ( scourge->getParty()->getParty( i ) == scourge->getCurrentBattle()->getCreature() ); } showCreatureInfo( scourge->getParty()->getParty( i ), player, ( scourge->getMap()->getSelectedDropTarget() && scourge->getMap()->getSelectedDropTarget()->creature == scourge->getParty()->getParty( i ) ), !scourge->getParty()->isPlayerOnly(), false ); } }
////////////////////////////////////////////////////////////////////////////// // 뱀파이어 오브젝트 핸들러 ////////////////////////////////////////////////////////////////////////////// void Darkness::execute(Vampire* pVampire, ObjectID_t TargetObjectID, VampireSkillSlot* pVampireSkillSlot, CEffectID_t CEffectID) throw(Error) { __BEGIN_TRY //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " Begin" << endl; Assert(pVampire != NULL); Assert(pVampireSkillSlot != NULL); try { Zone* pZone = pVampire->getZone(); Assert(pZone != NULL); Creature* pTargetCreature = pZone->getCreature(TargetObjectID); //Assert(pTargetCreature != NULL); // NoSuch제거. by sigi. 2002.5.2 if (pTargetCreature==NULL) { executeSkillFailException(pVampire, getSkillType()); return; } execute(pVampire, pTargetCreature->getX(), pTargetCreature->getY(), pVampireSkillSlot, CEffectID); } catch (Throwable & t) { executeSkillFailException(pVampire, getSkillType()); } //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl; __END_CATCH }
////////////////////////////////////////////////////////////////////////////// // 슬레이어 오브젝트 핸들러 ////////////////////////////////////////////////////////////////////////////// void ThunderFlash::execute(Slayer* pSlayer, ObjectID_t TargetObjectID, SkillSlot* pSkillSlot, CEffectID_t CEffectID) throw(Error) { __BEGIN_TRY //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " begin(slayerobject)" << endl; Assert(pSlayer != NULL); Assert(pSkillSlot != NULL); try { Zone* pZone = pSlayer->getZone(); Assert(pZone != NULL); Creature* pTargetCreature = pZone->getCreature(TargetObjectID); //Assert(pTargetCreature != NULL); // NoSuch제거. by sigi. 2002.5.2 if (pTargetCreature==NULL) { executeSkillFailException(pSlayer, getSkillType()); return; } execute(pSlayer, pTargetCreature->getX(), pTargetCreature->getY(), pSkillSlot, CEffectID); } catch (Throwable & t) { executeSkillFailException(pSlayer, getSkillType()); } //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " end(slayerobject)" << endl; __END_CATCH }
void CGSelectWayPointHandler::execute(CGSelectWayPoint* pPacket , Player* pPlayer) throw(Error) { __BEGIN_TRY __BEGIN_DEBUG_EX #ifdef __GAME_SERVER__ Assert(pPacket != NULL); Assert(pPlayer != NULL); static map<Level_t,Price_t> sPriceMap; try { int targetDynamicZoneType = g_pDynamicZoneInfoManager->getDynamicZoneTypeByZoneID(pPacket->getZoneID()); if (targetDynamicZoneType != DYNAMIC_ZONE_MAX) { executeEnterQuestZone(pPacket, pPlayer, targetDynamicZoneType); } // 게임 플레이어의 상태가 정상이 아니라면 걍 리턴한다. GamePlayer* pGamePlayer = dynamic_cast<GamePlayer*>(pPlayer); Assert(pGamePlayer != NULL); if (pGamePlayer->getPlayerStatus() != GPS_NORMAL) return; // 크리쳐가 슬레이어가 아니라면 리턴한다. Creature* pCreature = pGamePlayer->getCreature(); Assert(pCreature != NULL); PlayerCreature* pPC = dynamic_cast<PlayerCreature*>(pCreature); Assert(pPC != NULL); if (pPC->getStore()->isOpen()) return; if (pCreature->hasRelicItem()) return; // 크리쳐가 죽었으면 리턴 if (pCreature->isDead()) return; // 초보존으로 들어가는 경우엔 종족 상관없이 보내준다. if (pPacket->getZoneID() == 1122) { ZONE_COORD pos(1122); if (pCreature->isSlayer()) { pos.x = 107; pos.y = 27; } else if (pCreature->isVampire()) { pos.x = 18; pos.y = 27; } else if (pCreature->isOusters()) { pos.x = 12; pos.y = 103; } else return; if (!canEnterBeginnerZone(pCreature)) return; // 초보존이 유료존일수도 있을라나...? #if defined(__PAY_SYSTEM_ZONE__) || defined(__PAY_SYSTEM_FREE_LIMIT__) ZoneInfo* pZoneInfo = g_pZoneInfoManager->getZoneInfo(pos.id); // 유료존인데 유료사용자가 아니면... if (pZoneInfo == NULL || ((pZoneInfo->isPayPlay() || pZoneInfo->isPremiumZone()) && (!pGamePlayer->isPayPlaying() && !pGamePlayer->isFamilyFreePass()))) { //Statement* pStmt = NULL; string connectIP = pGamePlayer->getSocket()->getHost(); // 유료 서비스 사용이 가능한가? if (pGamePlayer->loginPayPlay(connectIP, pGamePlayer->getID())) { sendPayInfo(pGamePlayer); } else if (pZoneInfo->isPayPlay()) { // 유료 서비스 사용 불가인 경우 GCSystemMessage gcSystemMessage; if (g_pConfig->getPropertyInt("IsNetMarble") == 0) { gcSystemMessage.setMessage(g_pStringPool->getString(STRID_CANNOT_ENTER)); } else { gcSystemMessage.setMessage(g_pStringPool->getString(STRID_CANNOT_ENTER)); } pGamePlayer->sendPacket(&gcSystemMessage); return; } } #endif pPC->getGQuestManager()->illegalWarp(); transportCreature(pCreature, pos.id, pos.x, pos.y, false); return; } if (pPacket->getZoneID() == 1131) { if (g_pVariableManager->getVariable(ACTIVE_LEVEL_WAR) == 0) { GCSystemMessage gcSystemMessage; gcSystemMessage.setMessage(g_pStringPool->getString(STRID_CANNOT_ENTER)); pGamePlayer->sendPacket(&gcSystemMessage); return; } /* if (g_pConfig->getPropertyInt("ServerID" ) != 0 ) { GCNoticeEvent gcNoticeEvent; gcNoticeEvent.setCode(NOTICE_EVENT_NOT_FIRST_SERVER); pGamePlayer->sendPacket(&gcNoticeEvent); // GCSystemMessage gcSystemMessage; // gcSystemMessage.setMessage(g_pStringPool->getString(STRID_LEVEL_WAR_ONLY_FIRST_SERVER )); // pGamePlayer->sendPacket (&gcSystemMessage); return; } */ // 크리쳐 정보 보고 알아서 튕겨주자 =_=;; ZONE_COORD pos(g_pLevelWarZoneInfoManager->getCreatureZoneID(pCreature )); if (g_pSweeperBonusManager->isAble(g_pLevelWarZoneInfoManager->getCreatureZoneID(pCreature))) { GCSystemMessage gcSystemMessage; gcSystemMessage.setMessage(g_pStringPool->getString(STRID_NO_WAR_IN_ACTIVE )); pGamePlayer->sendPacket (&gcSystemMessage); return; } if (pCreature->isSlayer()) { pos.x = 12; pos.y = 9; } else if (pCreature->isVampire()) { pos.x = 117; pos.y = 8; } else if (pCreature->isOusters()) { pos.x = 9; pos.y = 111; } #if defined(__PAY_SYSTEM_ZONE__) || defined(__PAY_SYSTEM_FREE_LIMIT__) Zone* pZone = getZoneByZoneID(pos.id); Assert(pZone != NULL); LevelWarManager* pLevelWarManager = pZone->getLevelWarManager(); Assert(pLevelWarManager != NULL); if (!pLevelWarManager->hasWar() && !g_pVariableManager->canEnterLevelWarZoneFree() && !pGamePlayer->isPayPlaying() && pGamePlayer->isFamilyFreePass() && !pLevelWarManager->canEnterFreeUser()) { GCSystemMessage gcSystemMessage; gcSystemMessage.setMessage(g_pStringPool->getString(STRID_CANNOT_ENTER_LEVEL_WAR_ZONE)); pGamePlayer->sendPacket(&gcSystemMessage); return; } #endif pPC->getGQuestManager()->illegalWarp(); transportCreature(pCreature, pos.id, pos.x, pos.y, false); return; } if (pPacket->getZoneID() == 72) { if (!g_pWarSystem->hasActiveRaceWar()) { GCSystemMessage gcSystemMessage; gcSystemMessage.setMessage(g_pStringPool->getString(STRID_NO_WAR_IN_ACTIVE)); pGamePlayer->sendPacket (&gcSystemMessage); return; } /* if (g_pConfig->getPropertyInt("ServerID" ) != 0 ) { GCNoticeEvent gcNoticeEvent; gcNoticeEvent.setCode(NOTICE_EVENT_NOT_FIRST_SERVER); pGamePlayer->sendPacket(&gcNoticeEvent); // GCSystemMessage gcSystemMessage; // gcSystemMessage.setMessage(g_pStringPool->getString(STRID_LEVEL_WAR_ONLY_FIRST_SERVER )); // pGamePlayer->sendPacket (&gcSystemMessage); return; } */ // 크리쳐 정보 보고 알아서 튕겨주자 =_=;; ZONE_COORD pos; if (pCreature->isSlayer()) { pos.id = 73; pos.x = 30; pos.y = 124; } else if (pCreature->isVampire()) { pos.id = 71; pos.x = 104; pos.y = 128; } else if (pCreature->isOusters()) { pos.id = 72; pos.x = 67; pos.y = 165; } /*#if defined(__PAY_SYSTEM_ZONE__) || defined(__PAY_SYSTEM_FREE_LIMIT__) ZoneInfo* pZoneInfo = g_pZoneInfoManager->getZoneInfo(pos.id); // 유료존인데 유료사용자가 아니면... if (pZoneInfo==NULL || (pZoneInfo->isPayPlay() || pZoneInfo->isPremiumZone()) && (!pGamePlayer->isPayPlaying() && !pGamePlayer->isFamilyFreePass() )) { //Statement* pStmt = NULL; string connectIP = pGamePlayer->getSocket()->getHost(); // 유료 서비스 사용이 가능한가? if (pGamePlayer->loginPayPlay(connectIP, pGamePlayer->getID())) { sendPayInfo(pGamePlayer); } else if (pZoneInfo->isPayPlay()) { // 유료 서비스 사용 불가인 경우 GCSystemMessage gcSystemMessage; if (g_pConfig->getPropertyInt("IsNetMarble")==0) { gcSystemMessage.setMessage(g_pStringPool->getString(STRID_CANNOT_ENTER )); } else { gcSystemMessage.setMessage(g_pStringPool->getString(STRID_CANNOT_ENTER )); } pGamePlayer->sendPacket (&gcSystemMessage); return; } } #endif*/ if (!g_pVariableManager->isActiveRaceWarLimiter() || pCreature->isFlag(Effect::EFFECT_CLASS_RACE_WAR_JOIN_TICKET)) { pPC->getGQuestManager()->illegalWarp(); transportCreature(pCreature, pos.id, pos.x, pos.y, false); return; } else { GCSystemMessage gcSystemMessage; gcSystemMessage.setMessage(g_pStringPool->getString(STRID_CANNOT_ENTER_DURING_RACE_WAR)); pGamePlayer->sendPacket(&gcSystemMessage); return; } } if (!pCreature->isSlayer() && !pCreature->isOusters()) { // 뭔가를 해야하지 않을까? return; } if (pCreature->isFlag(Effect::EFFECT_CLASS_HAS_FLAG)) { // 뭔가를 해야하지 않을까? return; } if (pCreature->isFlag(Effect::EFFECT_CLASS_HAS_SWEEPER)) { // 뭔가를 해야하지 않을까? return; } //Slayer* pSlayer = dynamic_cast<Slayer*>(pCreature); //Assert(pSlayer != NULL); bool bCancel = false; // 이펙트가 걸려있어야 정상적인 이동이다. if (pCreature->isOusters() || (pCreature->isSlayer() && pCreature->isFlag(Effect::EFFECT_CLASS_SLAYER_PORTAL))) { ZoneID_t id = pPacket->getZoneID(); ZoneCoord_t x = pPacket->getX(); ZoneCoord_t y = pPacket->getY(); if (id == 0 && x == 0 && y == 0) { bCancel = true; } else { // 석화 상태일 경우 생깐다. if (pCreature->isFlag(Effect::EFFECT_CLASS_PARALYZE)) { bCancel = true; } // 웨이포인트 매니저를 통해서 클라이언트가 보내온 // 웨이포인트가 정상적인 웨이포인트인지를 검증한다. if (!g_pWayPointManager->isValidWayPoint(id, x, y, pCreature->getRace())) { // 뭔가를 해야하지 않을까? bCancel = true; //return; } try { if (!bCancel) { #if defined(__PAY_SYSTEM_ZONE__) || defined(__PAY_SYSTEM_FREE_LIMIT__) ZoneInfo* pZoneInfo = g_pZoneInfoManager->getZoneInfo(id); // 유료존인데 유료사용자가 아니면... if (pZoneInfo==NULL || ((pZoneInfo->isPayPlay() || pZoneInfo->isPremiumZone()) && (!pGamePlayer->isPayPlaying() && !pGamePlayer->isFamilyFreePass()))) { //Statement* pStmt = NULL; string connectIP = pGamePlayer->getSocket()->getHost(); // 유료 서비스 사용이 가능한가? if (pGamePlayer->loginPayPlay(connectIP, pGamePlayer->getID())) { sendPayInfo(pGamePlayer); } else if (pZoneInfo->isPayPlay()) { // 유료 서비스 사용 불가인 경우 GCSystemMessage gcSystemMessage; if (g_pConfig->getPropertyInt("IsNetMarble") == 0) { gcSystemMessage.setMessage(g_pStringPool->getString(STRID_CANNOT_ENTER)); } else { gcSystemMessage.setMessage(g_pStringPool->getString(STRID_CANNOT_ENTER)); } pGamePlayer->sendPacket (&gcSystemMessage); bCancel = true; } } #endif if (!bCancel) { // 이동시키기 전에 이펙트를 삭제한다. if (pCreature->isSlayer()) pCreature->removeFlag(Effect::EFFECT_CLASS_SLAYER_PORTAL); if (pCreature->isOusters()) { Ousters* pOusters = dynamic_cast<Ousters*>(pCreature); Assert(pOusters != NULL); GCNoticeEvent gcNoticeEvent; // 대지정령의 뿔을 사용할라면 시오람과 계약을 맺었어야 한다. if (!pOusters->getFlagSet()->isOn(FLAGSET_GNOMES_HORN)) { gcNoticeEvent.setCode(NOTICE_EVENT_CONTRACT_GNOMES_HORN); pPlayer->sendPacket(&gcNoticeEvent); return; } Level_t level = pOusters->getLevel(); Price_t price = sPriceMap[level]; if (price == 0) { price = (Price_t)(pow((double)level, 1.3) * 100) / 2; sPriceMap[level] = price; } /*if (g_pFlagManager->hasFlagWar() && pPacket->getZoneID() == 32 && pPacket->getX() == 124 && pPacket->getY() == 144 ) price = 0;*/ if (pOusters->getGold() < price) { gcNoticeEvent.setCode(NOTICE_EVENT_NOT_ENOUGH_MONEY); pPlayer->sendPacket(&gcNoticeEvent); return; } else { pOusters->decreaseGoldEx(price); GCModifyInformation gcMI; gcMI.addLongData(MODIFY_GOLD, pOusters->getGold()); pPlayer->sendPacket(&gcMI); } } // 올바른 웨이포인트라면 슬레이어를 이동시켜준다. pPC->getGQuestManager()->illegalWarp(); transportCreature(pCreature, id, x, y, false); } } } catch (NoSuchElementException&) { bCancel = true; } } } if (bCancel && pCreature->isSlayer()) { Zone* pZone = pCreature->getZone(); Assert(pZone != NULL); // id, x, y가 모두 0일 경우 이동을 취소한다는 뜻이다. pCreature->removeFlag(Effect::EFFECT_CLASS_SLAYER_PORTAL); // 헬기를 제거하라고 뿌려준다. GCAddHelicopter gcAddHelicopter; gcAddHelicopter.setObjectID(pCreature->getObjectID()); gcAddHelicopter.setCode(1); pZone->broadcastPacket(pCreature->getX(), pCreature->getY(), &gcAddHelicopter); } } catch (Throwable & t) { cerr << t.toString() << endl; } #endif // __GAME_SERVER__ __END_DEBUG_EX __END_CATCH }
////////////////////////////////////////////////////////////////////// // // Visible::execute() // ////////////////////////////////////////////////////////////////////// void Visible::execute(Slayer * pSlayer, ObjectID_t TargetObjectID, SkillSlot * pSkillSlot, CEffectID_t CEffectID) throw(Error) { __BEGIN_TRY //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " Begin" << endl; Assert(pSlayer != NULL); Assert(pSkillSlot != NULL); try { // Player를 받아온다. Player * pPlayer = pSlayer->getPlayer(); // Zone을 받아온다. Zone * pZone = pSlayer->getZone(); Creature * pTargetCreature = NULL; if (pSlayer->getObjectID() == TargetObjectID) pTargetCreature = pSlayer; else pTargetCreature = pZone->getCreature(TargetObjectID); SkillType_t SkillType = pSkillSlot->getSkillType(); //Assert (pTargetCreature != NULL); if (pTargetCreature == NULL || pTargetCreature->isNPC()) { executeSkillFailException(pSlayer, SkillType); //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl; return; } SkillInfo * pSkillInfo = g_pSkillInfoManager->getSkillInfo(SkillType); // 기술의 레벨을 받아온다. //SkillLevel_t SkillLevel = pSkillSlot->getExpLevel(); //SkillDomainType_t DomainType = pSkillInfo->getDomainType(); int RequiredMP = (int)pSkillInfo->getConsumeMP(); bool bManaCheck = hasEnoughMana(pSlayer, RequiredMP); bool bTimeCheck = verifyRunTime(pSkillSlot); bool bRangeCheck = verifyDistance(pSlayer, pTargetCreature, pSkillInfo->getRange()); bool bHit = false; // 기술성공률 검증. if (bManaCheck && bTimeCheck && bRangeCheck) { Coord_t myX = pSlayer->getX(), myY = pSlayer->getY(); Coord_t X = pTargetCreature->getX(), Y = pTargetCreature->getY(); Dir_t dir = calcDirection(myX, myY, X, Y); SkillInput input(pSlayer, pSkillSlot); SkillOutput output; computeOutput(input, output); GCSkillToTileOK1 _GCSkillToTileOK1; GCSkillToTileOK2 _GCSkillToTileOK2; GCSkillToTileOK3 _GCSkillToTileOK3; GCSkillToTileOK4 _GCSkillToTileOK4; GCSkillToTileOK5 _GCSkillToTileOK5; decreaseMana(pSlayer, RequiredMP, _GCSkillToTileOK1); // by sigi. 2002.11.12 VSRect rect(0, 0, pZone->getWidth()-1, pZone->getHeight()-1); list<Creature*> cList; int oX, oY; for(oX = -2; oX <= 2; oX++) for(oY = -2; oY <= 2; oY++) { int tileX = X+oX; int tileY = Y+oY; // by sigi. 2002.11.12 if (!rect.ptInRect(tileX, tileY)) continue; Tile& tile = pZone->getTile(tileX, tileY); pTargetCreature = NULL; if(tile.hasCreature(Creature::MOVE_MODE_WALKING)) pTargetCreature = tile.getCreature(Creature::MOVE_MODE_WALKING); if(pTargetCreature != NULL) { if(pTargetCreature->isPC()) { bool bHitRoll = HitRoll::isSuccessMagic(pSlayer, pSkillInfo, pSkillSlot); bool bEffected = pTargetCreature->isFlag(Effect::EFFECT_CLASS_INVISIBILITY); if(bHitRoll && bEffected ) { // 주위에 GCAddXXX를 보내고, effect manager에서 effect를 삭제하고, GCRemoveEffect를 보낸다. addVisibleCreature(pZone, pTargetCreature, true); _GCSkillToTileOK2.setObjectID(pSlayer->getObjectID()); _GCSkillToTileOK2.setSkillType(SkillType); _GCSkillToTileOK2.setX(X); _GCSkillToTileOK2.setY(Y); _GCSkillToTileOK2.setRange(dir); _GCSkillToTileOK2.setDuration(0); Player * pTargetPlayer = pTargetCreature->getPlayer(); Assert(pTargetPlayer != NULL); pTargetPlayer->sendPacket(&_GCSkillToTileOK2); cList.push_back(pTargetCreature); bHit = true; } } } // if(pTargetCreature!= NULL) } SkillDomainType_t DomainType = pSkillInfo->getDomainType(); // EXP UP! Exp_t Point = pSkillInfo->getPoint(); if(bHit ) { shareAttrExp(pSlayer, Point, 1, 1, 8, _GCSkillToTileOK1); increaseDomainExp(pSlayer, DomainType, pSkillInfo->getPoint(), _GCSkillToTileOK1); increaseSkillExp(pSlayer, DomainType, pSkillSlot, pSkillInfo, _GCSkillToTileOK1); } _GCSkillToTileOK1.setSkillType(SkillType); _GCSkillToTileOK1.setCEffectID(CEffectID); _GCSkillToTileOK1.setX(X); _GCSkillToTileOK1.setY(Y); _GCSkillToTileOK1.setRange(dir); _GCSkillToTileOK1.setDuration(0); _GCSkillToTileOK3.setObjectID(pSlayer->getObjectID()); _GCSkillToTileOK3.setSkillType(SkillType); _GCSkillToTileOK3.setX(X); _GCSkillToTileOK3.setY(Y); _GCSkillToTileOK4.setSkillType(SkillType); _GCSkillToTileOK4.setX(X); _GCSkillToTileOK4.setY(Y); _GCSkillToTileOK4.setDuration(0); _GCSkillToTileOK4.setRange(dir); _GCSkillToTileOK5.setObjectID(pSlayer->getObjectID()); _GCSkillToTileOK5.setSkillType(SkillType); _GCSkillToTileOK5.setX(X); _GCSkillToTileOK5.setY(Y); _GCSkillToTileOK5.setRange(dir); _GCSkillToTileOK5.setDuration(0); // Send Packet pPlayer->sendPacket(&_GCSkillToTileOK1); cList.push_back(pSlayer); cList = pZone->broadcastSkillPacket(myX, myY, X, Y, &_GCSkillToTileOK5, cList); pZone->broadcastPacket(myX, myY, &_GCSkillToTileOK3 , cList); pZone->broadcastPacket(X , Y, &_GCSkillToTileOK4 , cList); pSkillSlot->setRunTime(output.Delay); } else { executeSkillFailNormal(pSlayer, getSkillType(), NULL); } } catch(Throwable & t) { executeSkillFailException(pSlayer, getSkillType()); } //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl; __END_CATCH }
////////////////////////////////////////////////////////////////////////////// // 슬레이어 오브젝트 핸들러 ////////////////////////////////////////////////////////////////////////////// void RemoveCurse::execute(Slayer* pSlayer, ObjectID_t TargetObjectID, SkillSlot* pSkillSlot, CEffectID_t CEffectID) throw(Error) { __BEGIN_TRY //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " Begin" << endl; Assert(pSlayer != NULL); Assert(pSkillSlot != NULL); try { Player* pPlayer = pSlayer->getPlayer(); Zone* pZone = pSlayer->getZone(); Assert(pPlayer != NULL); Assert(pZone != NULL); Creature* pTargetCreature = pZone->getCreature(TargetObjectID); //Assert(pTargetCreature != NULL); // 슬레이어 외에는 치료할 수 없다. // NoSuch제거. by sigi. 2002.5.2 if (pTargetCreature==NULL || pTargetCreature->isSlayer() == false) { executeSkillFailException(pSlayer, getSkillType()); //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl; return; } GCSkillToObjectOK1 _GCSkillToObjectOK1; GCSkillToObjectOK2 _GCSkillToObjectOK2; GCSkillToObjectOK3 _GCSkillToObjectOK3; GCSkillToObjectOK4 _GCSkillToObjectOK4; GCSkillToObjectOK5 _GCSkillToObjectOK5; SkillType_t SkillType = pSkillSlot->getSkillType(); SkillInfo* pSkillInfo = g_pSkillInfoManager->getSkillInfo(SkillType); SkillDomainType_t DomainType = pSkillInfo->getDomainType(); // by sigi. 2002.12.3 SkillLevel_t SkillLevel = pSlayer->getINT()/2; //pSkillSlot->getExpLevel(); bool bDoom = false; bool bParalyze = false; bool bSeduction = false; // by sigi. 2002.12.3 //bool bHallucination = false; bool bDeath = false; bool bEffected = false; // 아무 저주나 걸려 있으면 켠다. EffectDoom* pEffectDoom = NULL; EffectParalyze* pEffectParalyze = NULL; EffectSeduction* pEffectSeduction = NULL; // by sigi. 2002.12.3 //EffectHallucination* pEffectHallucination = NULL; EffectDeath* pEffectDeath = NULL; if (pTargetCreature->isEffect(Effect::EFFECT_CLASS_DOOM)) { pEffectDoom = (EffectDoom*)pTargetCreature->findEffect(Effect::EFFECT_CLASS_DOOM); Assert(pEffectDoom != NULL); bDoom = HitRoll::isSuccessRemoveCurse(45, SkillLevel, 20, pEffectDoom->getLevel()/4); bEffected = true; } if (pTargetCreature->isEffect(Effect::EFFECT_CLASS_PARALYZE)) { pEffectParalyze = (EffectParalyze*)pTargetCreature->findEffect(Effect::EFFECT_CLASS_PARALYZE); Assert(pEffectParalyze != NULL); bParalyze = HitRoll::isSuccessRemoveCurse(45, SkillLevel, 10, pEffectParalyze->getLevel()/4); bEffected = true; } if (pTargetCreature->isEffect(Effect::EFFECT_CLASS_SEDUCTION)) { pEffectSeduction = (EffectSeduction*)pTargetCreature->findEffect(Effect::EFFECT_CLASS_SEDUCTION); Assert(pEffectSeduction != NULL); bSeduction = HitRoll::isSuccessRemoveCurse(45, SkillLevel, 30, pEffectSeduction->getLevel()/4); bEffected = true; } // by sigi. 2002.12.3 // if (pTargetCreature->isEffect(Effect::EFFECT_CLASS_HALLUCINATION)) // { // pEffectHallucination = (EffectHallucination*)pTargetCreature->findEffect(Effect::EFFECT_CLASS_HALLUCINATION); //// Assert(pEffectHallucination != NULL); // // bHallucination = HitRoll::isSuccessRemoveCurse(45, SkillLevel, 40, pEffectHallucination->getLevel()/4); // bEffected = true; // } if (pTargetCreature->isEffect(Effect::EFFECT_CLASS_DEATH)) { pEffectDeath = (EffectDeath*)pTargetCreature->findEffect(Effect::EFFECT_CLASS_DEATH); Assert(pEffectDeath != NULL); bDeath = HitRoll::isSuccessRemoveCurse(45, SkillLevel, 50, pEffectDeath->getLevel()/4); bEffected = true; } int RequiredMP = (int)pSkillInfo->getConsumeMP(); bool bManaCheck = hasEnoughMana(pSlayer, RequiredMP); bool bTimeCheck = verifyRunTime(pSkillSlot); bool bRangeCheck = verifyDistance(pSlayer, pTargetCreature, pSkillInfo->getRange()); // 마나가 있고, 시간이 됐고, 거리가 적당하며, // 저주가 하나라도 걸려있어야 한다. if (bManaCheck && bTimeCheck && bRangeCheck && bEffected) { decreaseMana(pSlayer, RequiredMP, _GCSkillToObjectOK1); SkillInput input(pSlayer, pSkillSlot); SkillOutput output; computeOutput(input, output); // 각각의 저주를 삭제하고, // 패킷에다 이펙트 삭제하라고 더한다. GCRemoveEffect gcRemoveEffect; gcRemoveEffect.setObjectID(pTargetCreature->getObjectID()); if (bDoom) { pEffectDoom->setDeadline(0); pTargetCreature->removeFlag(Effect::EFFECT_CLASS_DOOM); gcRemoveEffect.addEffectList(Effect::EFFECT_CLASS_DOOM); } if (bParalyze) { pEffectParalyze->setDeadline(0); pTargetCreature->removeFlag(Effect::EFFECT_CLASS_PARALYZE); gcRemoveEffect.addEffectList(Effect::EFFECT_CLASS_PARALYZE); } if (bSeduction) { pEffectSeduction->setDeadline(0); pTargetCreature->removeFlag(Effect::EFFECT_CLASS_SEDUCTION); gcRemoveEffect.addEffectList(Effect::EFFECT_CLASS_SEDUCTION); } // by sigi. 2002.12.3 // if (bHallucination) // { // pEffectHallucination->setDeadline(0); // pTargetCreature->removeFlag(Effect::EFFECT_CLASS_HALLUCINATION); // gcRemoveEffect.addEffectList(Effect::EFFECT_CLASS_HALLUCINATION); // } if (bDeath) { pEffectDeath->setDeadline(0); pTargetCreature->removeFlag(Effect::EFFECT_CLASS_DEATH); gcRemoveEffect.addEffectList(Effect::EFFECT_CLASS_DEATH); } // 경험치를 올린다. SkillGrade Grade = g_pSkillInfoManager->getGradeByDomainLevel(pSlayer->getSkillDomainLevel(DomainType)); Exp_t ExpUp = 10*(Grade+1); shareAttrExp(pSlayer, ExpUp, 1, 1, 8, _GCSkillToObjectOK1); increaseDomainExp(pSlayer, DomainType, pSkillInfo->getPoint(), _GCSkillToObjectOK1); increaseSkillExp(pSlayer, DomainType, pSkillSlot, pSkillInfo, _GCSkillToObjectOK1); // 패킷을 만들어 보낸다. ZoneCoord_t myX = pSlayer->getX(); ZoneCoord_t myY = pSlayer->getY(); ZoneCoord_t targetX = pTargetCreature->getX(); ZoneCoord_t targetY = pTargetCreature->getY(); _GCSkillToObjectOK1.setSkillType(SkillType); _GCSkillToObjectOK1.setCEffectID(CEffectID); _GCSkillToObjectOK1.setTargetObjectID(TargetObjectID); _GCSkillToObjectOK1.setDuration(0); _GCSkillToObjectOK2.setObjectID(pSlayer->getObjectID()); _GCSkillToObjectOK2.setSkillType(SkillType); _GCSkillToObjectOK2.setDuration (0); _GCSkillToObjectOK3.setObjectID(pSlayer->getObjectID()); _GCSkillToObjectOK3.setSkillType(SkillType); _GCSkillToObjectOK3.setTargetXY(targetX, targetY); _GCSkillToObjectOK4.setSkillType(SkillType); _GCSkillToObjectOK4.setTargetObjectID(TargetObjectID); _GCSkillToObjectOK5.setObjectID(pSlayer->getObjectID()); _GCSkillToObjectOK5.setSkillType(SkillType); _GCSkillToObjectOK5.setTargetObjectID (TargetObjectID); _GCSkillToObjectOK5.setDuration (0); pPlayer->sendPacket(&_GCSkillToObjectOK1); if (pTargetCreature->isPC()) { Player* pTargetPlayer = pTargetCreature->getPlayer(); pTargetPlayer->sendPacket(&_GCSkillToObjectOK2); } pZone->broadcastPacket(targetX, targetY, &gcRemoveEffect); list< Creature*> cList; cList.push_back(pSlayer); cList.push_back(pTargetCreature); cList = pZone->broadcastSkillPacket(myX, myY, targetX, targetY, &_GCSkillToObjectOK5 , cList); pZone->broadcastPacket(myX, myY, &_GCSkillToObjectOK3 , cList); pZone->broadcastPacket(targetX, targetY, &_GCSkillToObjectOK4 , cList); pSkillSlot->setRunTime(output.Delay); } else { executeSkillFailNormal(pSlayer, getSkillType(), pTargetCreature); } } catch(Throwable & t) { executeSkillFailException(pSlayer, getSkillType()); } //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl; __END_CATCH }
////////////////////////////////////////////////////////////////////////////// // 뱀파이어 오브젝트 핸들러 ////////////////////////////////////////////////////////////////////////////// void Death::execute(Vampire* pVampire, ObjectID_t TargetObjectID, VampireSkillSlot* pSkillSlot, CEffectID_t CEffectID) throw(Error) { __BEGIN_TRY //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << "begin " << endl; Assert(pVampire != NULL); Assert(pSkillSlot != NULL); try { Player* pPlayer = pVampire->getPlayer(); Zone* pZone = pVampire->getZone(); Assert(pPlayer != NULL); Assert(pZone != NULL); Creature* pTargetCreature = pZone->getCreature(TargetObjectID); //Assert(pTargetCreature != NULL); // NPC는 공격할 수 없다. // 저주 면역. by sigi. 2002.9.13 // NoSuch제거. by sigi. 2002.5.2 if (pTargetCreature==NULL || pTargetCreature->isFlag(Effect::EFFECT_CLASS_IMMUNE_TO_CURSE) || !canAttack(pVampire, pTargetCreature ) || pTargetCreature->isNPC()) { executeSkillFailException(pVampire, getSkillType()); //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " end " << endl; return; } GCSkillToObjectOK1 _GCSkillToObjectOK1; GCSkillToObjectOK2 _GCSkillToObjectOK2; GCSkillToObjectOK3 _GCSkillToObjectOK3; GCSkillToObjectOK4 _GCSkillToObjectOK4; GCSkillToObjectOK5 _GCSkillToObjectOK5; GCSkillToObjectOK6 _GCSkillToObjectOK6; SkillType_t SkillType = pSkillSlot->getSkillType(); SkillInfo* pSkillInfo = g_pSkillInfoManager->getSkillInfo(SkillType); // Knowledge of Curse 가 있다면 hit bonus 10 int HitBonus = 0; if (pVampire->hasRankBonus(RankBonus::RANK_BONUS_KNOWLEDGE_OF_CURSE ) ) { RankBonus* pRankBonus = pVampire->getRankBonus(RankBonus::RANK_BONUS_KNOWLEDGE_OF_CURSE); Assert(pRankBonus != NULL); HitBonus = pRankBonus->getPoint(); } int RequiredMP = decreaseConsumeMP(pVampire, pSkillInfo); bool bManaCheck = hasEnoughMana(pVampire, RequiredMP); bool bTimeCheck = verifyRunTime(pSkillSlot); bool bRangeCheck = verifyDistance(pVampire, pTargetCreature, pSkillInfo->getRange()); bool bHitRoll = HitRoll::isSuccessVampireCurse(pSkillInfo->getLevel(), pTargetCreature->getResist(MAGIC_DOMAIN_CURSE)); bool bHitRoll2 = HitRoll::isSuccessMagic(pVampire, pSkillInfo, pSkillSlot, HitBonus); bool bCanHit = canHit(pVampire, pTargetCreature, SkillType); bool bEffected = pTargetCreature->isFlag(Effect::EFFECT_CLASS_DEATH); bool bPK = verifyPK(pVampire, pTargetCreature); ZoneCoord_t targetX = pTargetCreature->getX(); ZoneCoord_t targetY = pTargetCreature->getY(); ZoneCoord_t myX = pVampire->getX(); ZoneCoord_t myY = pVampire->getY(); if (bManaCheck && bTimeCheck && bRangeCheck && bHitRoll && bHitRoll2 && bCanHit && !bEffected && bPK) { decreaseMana(pVampire, RequiredMP, _GCSkillToObjectOK1); bool bCanSeeCaster = canSee(pTargetCreature, pVampire); SkillInput input(pVampire); SkillOutput output; computeOutput(input, output); // pTargetCreature가 저주마법을 반사하는 경우 if (CheckReflection(pVampire, pTargetCreature, getSkillType())) { pTargetCreature = (Creature*)pVampire; TargetObjectID = pVampire->getObjectID(); } Resist_t resist = pTargetCreature->getResist(MAGIC_DOMAIN_CURSE); if ((resist*10/3) > output.Duration ) output.Duration=0; else output.Duration -= resist*10/3; if (output.Duration < 20 ) output.Duration = 20; // 이펙트 오브젝트를 생성해 붙인다. EffectDeath* pEffect = new EffectDeath(pTargetCreature); pEffect->setDeadline(output.Duration); pEffect->setLevel(pSkillInfo->getLevel()/2); pEffect->setResistPenalty(output.Damage); pTargetCreature->addEffect(pEffect); pTargetCreature->setFlag(Effect::EFFECT_CLASS_DEATH); // 능력치를 계산해서 보내준다. if (pTargetCreature->isSlayer()) { Slayer* pTargetSlayer = dynamic_cast<Slayer*>(pTargetCreature); if (bCanSeeCaster) { SLAYER_RECORD prev; pTargetSlayer->getSlayerRecord(prev); pTargetSlayer->initAllStat(); pTargetSlayer->addModifyInfo(prev, _GCSkillToObjectOK2); } else { SLAYER_RECORD prev; pTargetSlayer->getSlayerRecord(prev); pTargetSlayer->initAllStat(); pTargetSlayer->addModifyInfo(prev, _GCSkillToObjectOK6); } } else if (pTargetCreature->isVampire()) { Vampire* pTargetVampire = dynamic_cast<Vampire*>(pTargetCreature); VAMPIRE_RECORD prev; pTargetVampire->getVampireRecord(prev); pTargetVampire->initAllStat(); if (bCanSeeCaster) { pTargetVampire->addModifyInfo(prev, _GCSkillToObjectOK2); } else { pTargetVampire->addModifyInfo(prev, _GCSkillToObjectOK6); } } else if (pTargetCreature->isOusters()) { Ousters* pTargetOusters = dynamic_cast<Ousters*>(pTargetCreature); OUSTERS_RECORD prev; pTargetOusters->getOustersRecord(prev); pTargetOusters->initAllStat(); if (bCanSeeCaster) { pTargetOusters->addModifyInfo(prev, _GCSkillToObjectOK2); } else { pTargetOusters->addModifyInfo(prev, _GCSkillToObjectOK6); } } else if (pTargetCreature->isMonster()) { Monster* pTargetMonster = dynamic_cast<Monster*>(pTargetCreature); pTargetMonster->initAllStat(); } else Assert(false); _GCSkillToObjectOK1.setSkillType(SkillType); _GCSkillToObjectOK1.setCEffectID(CEffectID); _GCSkillToObjectOK1.setTargetObjectID(TargetObjectID); _GCSkillToObjectOK1.setDuration(output.Duration); _GCSkillToObjectOK2.setObjectID(pVampire->getObjectID()); _GCSkillToObjectOK2.setSkillType(SkillType); _GCSkillToObjectOK2.setDuration(output.Duration); _GCSkillToObjectOK3.setObjectID(pVampire->getObjectID()); _GCSkillToObjectOK3.setSkillType(SkillType); _GCSkillToObjectOK3.setTargetXY (targetX, targetY); _GCSkillToObjectOK4.setSkillType(SkillType); _GCSkillToObjectOK4.setTargetObjectID(TargetObjectID); _GCSkillToObjectOK4.setDuration(output.Duration); _GCSkillToObjectOK5.setObjectID(pVampire->getObjectID()); _GCSkillToObjectOK5.setSkillType(SkillType); _GCSkillToObjectOK5.setTargetObjectID (TargetObjectID); _GCSkillToObjectOK5.setDuration(output.Duration); _GCSkillToObjectOK6.setXY(myX, myY); _GCSkillToObjectOK6.setSkillType(SkillType); _GCSkillToObjectOK6.setDuration(output.Duration); if (bCanSeeCaster) // 10은 땜빵 수치다. { computeAlignmentChange(pTargetCreature, 10, pVampire, &_GCSkillToObjectOK2, &_GCSkillToObjectOK1); } else // 10은 땜빵 수치다. { computeAlignmentChange(pTargetCreature, 10, pVampire, &_GCSkillToObjectOK6, &_GCSkillToObjectOK1); } list<Creature *> cList; cList.push_back(pTargetCreature); cList.push_back(pVampire); cList = pZone->broadcastSkillPacket(myX, myY, targetX, targetY, &_GCSkillToObjectOK5, cList); pZone->broadcastPacket(myX, myY, &_GCSkillToObjectOK3, cList); pZone->broadcastPacket(targetX, targetY, &_GCSkillToObjectOK4, cList); // Send Packet pPlayer->sendPacket(&_GCSkillToObjectOK1); if (pTargetCreature->isPC()) { Player* pTargetPlayer = pTargetCreature->getPlayer(); if (pTargetPlayer == NULL) { //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " end " << endl; return; } if (bCanSeeCaster) pTargetPlayer->sendPacket(&_GCSkillToObjectOK2); else pTargetPlayer->sendPacket(&_GCSkillToObjectOK6); } else if (pTargetCreature->isMonster()) { Monster* pTargetMonster = dynamic_cast<Monster*>(pTargetCreature); pTargetMonster->addEnemy(pVampire); } GCAddEffect gcAddEffect; gcAddEffect.setObjectID(TargetObjectID); gcAddEffect.setEffectID(Effect::EFFECT_CLASS_DEATH); gcAddEffect.setDuration(output.Duration); pZone->broadcastPacket(targetX, targetY, &gcAddEffect); //cout << pTargetCreature->getName() << "에게 Death를 " << output.Duration << " duration 동안 건다." << endl; pSkillSlot->setRunTime(output.Delay); } else { executeSkillFailNormal(pVampire, getSkillType(), pTargetCreature); } } catch (Throwable & t) { executeSkillFailException(pVampire, getSkillType()); } //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " end " << endl; __END_CATCH }
////////////////////////////////////////////////////////////////////////////// // 클라이언트가 CGLogout 패킷을 보내면, 게임 서버는 크리처를 존에서 삭제하고, // 크리처와 아이템 정보를 DB에 저장한 후, 접속을 종료한다. ////////////////////////////////////////////////////////////////////////////// void CGLogoutHandler::execute (CGLogout* pPacket , Player* pPlayer) throw(ProtocolException , Error) { __BEGIN_TRY __BEGIN_DEBUG_EX #ifdef __GAME_SERVER__ // Assert(pPacket != NULL); Assert(pPlayer != NULL); // 새로그인 구조에서는 Logout을 하면 대기 상태로 나가야 한다. // Logout 패킷을 받으면 플레이어를 IncomingPlayerManager로 보낸다. GamePlayer* pGamePlayer = dynamic_cast<GamePlayer*>(pPlayer); //cout << "CGLogoutHandler: " << pGamePlayer->getID() << endl; Creature* pCreature = pGamePlayer->getCreature(); Assert(pCreature != NULL); Zone* pZone = pCreature->getZone(); Assert(pZone != NULL); // 나는 나간다 라고 로그를 남긴다. pGamePlayer->logLoginoutDateTime(); try { // 로그아웃할때 성물, 피의 성서 조각을 떨어뜨린다. // bool bSendPacket = false; // dropRelicToZone(pCreature, bSendPacket); if (pCreature->isPLAYER() && g_pPKZoneInfoManager->isPKZone(pCreature->getZoneID() ) ) { g_pPKZoneInfoManager->leavePKZone(pCreature->getZoneID()); } if (g_pConfig->hasKey("Hardcore") && g_pConfig->getPropertyInt("Hardcore")!=0 && pPacket==NULL ) { } else { // 크리처의 정보를 저장한다. pCreature->save(); if (pCreature->isSlayer() ) { Slayer* pSlayer = dynamic_cast<Slayer*>(pCreature); pSlayer->tinysave("LastPlayDate=now()"); } else if (pCreature->isVampire() ) { Vampire* pVampire = dynamic_cast<Vampire*>(pCreature); pVampire->tinysave("LastPlayDate=now()"); } else if (pCreature->isOusters() ) { Ousters* pOusters = dynamic_cast<Ousters*>(pCreature); pOusters->tinysave("LastPlayDate=now()"); } ////////////////////////////////////////////////////////////// // 플레이어가 COMA상태(현재 죽은 상태)라면 로그아웃시 자동으로 // 부활위치로 캐릭터를 이동시킨다. // Login/Logout의 반복으로 부활기술을 사용하지 못하게 함 // // Creature의 정보를 먼저 DB에 업데이트한 후 새로 업데이트를 한다. ////////////////////////////////////////////////////////////// // 이터니티를 한번 쓴 상태로 로그아웃하면 부활 위치로 날라간다. if (pCreature->isFlag(Effect::EFFECT_CLASS_COMA) || pCreature->isFlag(Effect::EFFECT_CLASS_ETERNITY)) { //cout << "COMA 상태에서 로그아웃했음" << endl; ZoneID_t ZoneID = 0; ZoneCoord_t ZoneX = 0; ZoneCoord_t ZoneY = 0; ZONE_COORD ResurrectCoord; if (pCreature->isPC() ) { PlayerCreature* pPC = dynamic_cast<PlayerCreature*>(pCreature); g_pResurrectLocationManager->getPosition(pPC, ResurrectCoord); ZoneID = ResurrectCoord.id; ZoneX = ResurrectCoord.x; ZoneY = ResurrectCoord.y; char pField[80]; sprintf(pField, "ZoneID=%d, XCoord=%d, YCoord=%d, CurrentHP=HP", ZoneID, ZoneX, ZoneY); if (pPC->isSlayer() ) { Slayer* pSlayer = dynamic_cast<Slayer*>(pPC); pSlayer->tinysave(pField); } else if (pPC->isVampire() ) { Vampire* pVampire = dynamic_cast<Vampire*>(pPC); pVampire->tinysave(pField); } else if (pPC->isOusters() ) { Ousters* pOusters = dynamic_cast<Ousters*>(pPC); pOusters->tinysave(pField); } } } // 포스 스크롤이 켜져 있으면 로그아웃하면저 저장한다. if (pCreature->isFlag(Effect::EFFECT_CLASS_BEHEMOTH_FORCE_SCROLL) ) { Effect* pEffect = pCreature->findEffect(Effect::EFFECT_CLASS_BEHEMOTH_FORCE_SCROLL); pEffect->save(pCreature->getName()); } if (pCreature->isFlag(Effect::EFFECT_CLASS_SAFE_FORCE_SCROLL) ) { Effect* pEffect = pCreature->findEffect(Effect::EFFECT_CLASS_SAFE_FORCE_SCROLL); pEffect->save(pCreature->getName()); } if (pCreature->isFlag(Effect::EFFECT_CLASS_CARNELIAN_FORCE_SCROLL) ) { Effect* pEffect = pCreature->findEffect(Effect::EFFECT_CLASS_CARNELIAN_FORCE_SCROLL); pEffect->save(pCreature->getName()); } /* if(pCreature->isSlayer()) { Slayer* pSlayer = dynamic_cast<Slayer*>(pCreature); Assert(pSlayer != NULL); if (g_pResurrectLocationManager->getSlayerPosition(pSlayer->getResurrectZoneID(), ResurrectCoord)) { ZoneID = ResurrectCoord.id; ZoneX = ResurrectCoord.x; ZoneY = ResurrectCoord.y; } else { if (g_pResurrectLocationManager->getSlayerPosition(pSlayer->getZone()->getZoneID(), ResurrectCoord)) { ZoneID = ResurrectCoord.id; ZoneX = ResurrectCoord.x; ZoneY = ResurrectCoord.y; } else { throw Error("Critical Error: ResurrectInfo is not established"); } } char pField[80]; sprintf(pField, "ZoneID=%d, XCoord=%d, YCoord=%d, CurrentHP=HP", ZoneID, ZoneX, ZoneY); pSlayer->tinysave(pField); } else if(pCreature->isVampire()) { Vampire* pVampire = dynamic_cast<Vampire*>(pCreature); Assert(pVampire != NULL); if (g_pResurrectLocationManager->getVampirePosition(pVampire->getResurrectZoneID(), ResurrectCoord)) { ZoneID = ResurrectCoord.id; ZoneX = ResurrectCoord.x; ZoneY = ResurrectCoord.y; } else { if (g_pResurrectLocationManager->getVampirePosition(pVampire->getZone()->getZoneID(), ResurrectCoord)) { ZoneID = ResurrectCoord.id; ZoneX = ResurrectCoord.x; ZoneY = ResurrectCoord.y; } else { throw Error("Critical Error: ResurrectInfo is not established"); } } // 이제 정보를 저장한다. char pField[80]; sprintf(pField, "ZoneID=%d, XCoord=%d, YCoord=%d, CurrentHP=HP", ZoneID, ZoneX, ZoneY); pVampire->tinysave(pField); } */ } // // 이제, 존에서 PC를 삭제한다. // // *CAUTION* // // pCreature의 좌표가 실제로 pCreature가 존재하는 타일의 좌표와 같아야 한다. // 따라서, 이 메쏘드를 호출하기 전에 좌표를 잘 바꿔놔야 한당.. // pZone->deleteCreature(pCreature , pCreature->getX() , pCreature->getY()); ////cout << "PC deleted from Zone >> "; // 존그룹의 ZPM에서 플레이어를 삭제한다. // ZonePlayerManager의 ProcessCommand 안에서 지우는 것이므로 반드시 NoBlocked 으로 지워야 한다. pZone->getZoneGroup()->getZonePlayerManager()->deletePlayer(pGamePlayer->getSocket()->getSOCKET()); // IPM으로 플레이어를 옮긴다. //g_pIncomingPlayerManager->pushPlayer(pGamePlayer); // Core의 구조를 바꾸면서 쓰레드로 부터 독립적으로 행하기 위하여 뒤에 한꺼번에 처리하기 위해서 // OutList로 넣는다. pZone->getZoneGroup()->getZonePlayerManager()->pushOutPlayer(pGamePlayer); ////cout << "Move PC to IPM >> "; } catch (NoSuchElementException & nsee) { throw DisconnectException(); } // 로그인 서버로 GLIncomingConnection을 보낸다. // PlayerName과 ClientIP를 같이 실어서 보낸다. /* GLIncomingConnection glIncomingConnection; glIncomingConnection.setPlayerID(pGamePlayer->getID()); glIncomingConnection.setClientIP(pGamePlayer->getSocket()->getHost()); if (g_pConfig->getProperty("User") == "excel96") g_pLoginServerManager->sendPacket("211.117.52.12" , g_pConfig->getPropertyInt("LoginServerUDPPort"), &glIncomingConnection); else if (g_pConfig->getProperty("User") == "elcastle") g_pLoginServerManager->sendPacket("211.117.52.12" , g_pConfig->getPropertyInt("LoginServerUDPPort"), &glIncomingConnection); else if (g_pConfig->getProperty("User") == "elca") g_pLoginServerManager->sendPacket("211.117.52.12" , g_pConfig->getPropertyInt("LoginServerUDPPort"), &glIncomingConnection); */ pGamePlayer->setPlayerStatus(GPS_AFTER_SENDING_GL_INCOMING_CONNECTION); #endif __END_DEBUG_EX __END_CATCH }
void CGSkillToNamedHandler::execute (CGSkillToNamed* pPacket , Player* pPlayer) throw(Error) { __BEGIN_TRY __BEGIN_DEBUG_EX #ifdef __GAME_SERVER__ Assert(pPacket != NULL); Assert(pPlayer != NULL); try { GamePlayer* pGamePlayer = dynamic_cast<GamePlayer*>(pPlayer); Assert(pGamePlayer != NULL); // by sigi if (pGamePlayer->getPlayerStatus() != GPS_NORMAL) return; Creature* pCreature = pGamePlayer->getCreature(); Assert(pCreature != NULL); // by sigi Zone* pZone = pCreature->getZone(); Assert(pZone != NULL); SkillType_t SkillType = pPacket->getSkillType(); // 완전 안전지대라면 기술 사용 불가. by sigi. 2002.11.14 ZoneLevel_t ZoneLevel = pZone->getZoneLevel(pCreature->getX(), pCreature->getY()); if ((ZoneLevel & COMPLETE_SAFE_ZONE) || (pCreature->isFlag(Effect::EFFECT_CLASS_PARALYZE)) || (pCreature->isFlag(Effect::EFFECT_CLASS_CAUSE_CRITICAL_WOUNDS)) || (pCreature->isFlag(Effect::EFFECT_CLASS_EXPLOSION_WATER)) || (pCreature->isFlag(Effect::EFFECT_CLASS_COMA))) { GCSkillFailed1 _GCSkillFailed1; _GCSkillFailed1.setSkillType(SkillType); pPlayer->sendPacket(&_GCSkillFailed1); return; } if (pCreature->isFlag(Effect::EFFECT_CLASS_TRANSFORM_TO_WERWOLF)) { switch(SkillType) { case SKILL_ATTACK_MELEE: case SKILL_BITE_OF_DEATH: case SKILL_UN_TRANSFORM: case SKILL_RAPID_GLIDING: break; default: GCSkillFailed1 _GCSkillFailed1; _GCSkillFailed1.setSkillType(SkillType); pPlayer->sendPacket(&_GCSkillFailed1); dynamic_cast<Vampire*>(pCreature)->sendVampireSkillInfo(); return; } } disableFlags(pCreature, pZone, SkillType); if (pCreature->isSlayer()) { Slayer* pSlayer = dynamic_cast<Slayer*>(pCreature); SkillSlot* pSkillSlot = ((Slayer *)pCreature)->hasSkill(SkillType); bool bSuccess = true; if (pSkillSlot == NULL) bSuccess = false; if (!isAbleToUseSelfSkill(pSlayer, SkillType)) bSuccess = false; /* if (pSlayer->isFlag(Effect::EFFECT_CLASS_SNIPING_MODE)) { g_Sniping.checkRevealRatio(pSlayer, 20, 10); } */ if (bSuccess) { SkillHandler* pSkillHandler = g_pSkillHandlerManager->getSkillHandler(SkillType); Assert(pSkillHandler != NULL); pSkillHandler->execute(pSlayer, pPacket->getTargetName(), pSkillSlot, pPacket->getCEffectID()); } else { GCSkillFailed1 _GCSkillFailed1; _GCSkillFailed1.setSkillType(SkillType); pPlayer->sendPacket(&_GCSkillFailed1); } } else if (pCreature->isVampire()) { Vampire* pVampire = dynamic_cast<Vampire*>(pCreature); VampireSkillSlot* pVampireSkillSlot = ((Vampire *)pCreature)->hasSkill(SkillType); bool bSuccess = true; //cout << "SkillType:" << (int)SkillType << endl; /* if (pVampire->isFlag(Effect::EFFECT_CLASS_EXTREME)) { EffectManager * pEffectManager = pVampire->getEffectManager(); Assert(pEffectManager != NULL); Effect * pEffect = pEffectManager->findEffect(Effect::EFFECT_CLASS_EXTREME); if (pEffect != NULL ) { pEffect->setDeadline(0); } } */ if (pVampireSkillSlot == NULL) bSuccess = false; if (!isAbleToUseSelfSkill(pVampire, SkillType)) bSuccess = false; /* if (pVampire->isFlag(Effect::EFFECT_CLASS_INVISIBILITY)) { addVisibleCreature(pZone, pVampire, true); } */ if (bSuccess) { SkillHandler* pSkillHandler = g_pSkillHandlerManager->getSkillHandler(SkillType); Assert(pSkillHandler != NULL); pSkillHandler->execute(pVampire, pPacket->getTargetName(), pVampireSkillSlot, pPacket->getCEffectID()); } else { GCSkillFailed1 _GCSkillFailed1; _GCSkillFailed1.setSkillType(SkillType); pPlayer->sendPacket(&_GCSkillFailed1); } } else if (pCreature->isOusters()) { Ousters* pOusters = dynamic_cast<Ousters*>(pCreature); OustersSkillSlot* pOustersSkillSlot = ((Ousters *)pCreature)->hasSkill(SkillType); bool bSuccess = true; if (pOustersSkillSlot == NULL) bSuccess = false; if (!isAbleToUseSelfSkill(pOusters, SkillType)) bSuccess = false; if (bSuccess) { SkillHandler* pSkillHandler = g_pSkillHandlerManager->getSkillHandler(SkillType); Assert(pSkillHandler != NULL); pSkillHandler->execute(pOusters, pPacket->getTargetName(), pOustersSkillSlot, pPacket->getCEffectID()); } else { GCSkillFailed1 _GCSkillFailed1; _GCSkillFailed1.setSkillType(SkillType); pPlayer->sendPacket(&_GCSkillFailed1); } } } catch (Throwable & t) { //cout << t.toString() << endl; } #endif // __GAME_SERVER__ __END_DEBUG_EX __END_CATCH }
void SimpleMissileSkill::execute( Ousters* pOusters, ObjectID_t TargetObjectID, OustersSkillSlot* pOustersSkillSlot, const SIMPLE_SKILL_INPUT& param, SIMPLE_SKILL_OUTPUT& result, CEffectID_t CEffectID, int HitBonus) throw(Error) { __BEGIN_TRY Assert(pOusters != NULL); Assert(pOustersSkillSlot != NULL); try { Player* pPlayer = pOusters->getPlayer(); Zone* pZone = pOusters->getZone(); Assert(pPlayer != NULL); Assert(pZone != NULL); Creature* pTargetCreature = pZone->getCreature(TargetObjectID); // NPC는 공격할 수가 없다. // NoSuch제거. by sigi. 2002.5.2 if (pTargetCreature==NULL || !canAttack(pOusters, pTargetCreature ) || pTargetCreature->isNPC() ) { executeSkillFailException(pOusters, param.SkillType, param.Grade); return; } result.pTargetCreature = pTargetCreature; GCSkillToObjectOK1 _GCSkillToObjectOK1; GCSkillToObjectOK2 _GCSkillToObjectOK2; GCSkillToObjectOK3 _GCSkillToObjectOK3; GCSkillToObjectOK4 _GCSkillToObjectOK4; GCSkillToObjectOK5 _GCSkillToObjectOK5; GCSkillToObjectOK6 _GCSkillToObjectOK6; if (param.ItemClass != Item::ITEM_CLASS_MAX) { Item* pItem = pOusters->getWearItem(Ousters::WEAR_RIGHTHAND); if (pItem == NULL || pItem->getItemClass() != param.ItemClass || !pOusters->isRealWearingEx(Ousters::WEAR_RIGHTHAND)) { executeSkillFailException(pOusters, param.SkillType, param.Grade); return; } } SkillInfo* pSkillInfo = g_pSkillInfoManager->getSkillInfo(param.SkillType); bool bCriticalHit = false; Damage_t Damage = 0; if (param.bAdd) { // 파라미터로 전달된 데미지 값이 더해지는 데미지라면, // 일반 데미지를 계산 후, 데미지를 더해야 한다. // 파라미터로 전달된 데미지 값이 직접적으로 쓰이는 데미지라면, // 이 부분까지 들어오지 않으므로, 밑의 부분까지 0으로 전달된다. Damage += computeDamage(pOusters, pTargetCreature, 0, bCriticalHit); } if (param.bMagicDamage) { // 만일 스킬 데미지가 마법 데미지라면, 마법 데미지 계산 함수를 이용해 계산을 해준다. // Damage += computeMagicDamage(pTargetCreature, param.SkillDamage, param.SkillType, true); Damage += computeOustersMagicDamage(pOusters, pTargetCreature, param.SkillDamage, param.SkillType); } else { Damage += param.SkillDamage; } computeCriticalBonus(pOusters, param.SkillType, Damage, bCriticalHit); int RequiredMP = (int)pSkillInfo->getConsumeMP(); bool bManaCheck = hasEnoughMana(pOusters, RequiredMP); bool bTimeCheck = verifyRunTime(pOustersSkillSlot); bool bRangeCheck = verifyDistance(pOusters, pTargetCreature, pSkillInfo->getRange()); bool bHitRoll = false; bool bCanHit = canHit(pOusters, pTargetCreature, param.SkillType); bool bPK = verifyPK(pOusters, pTargetCreature); bool bSatisfyRequire = pOusters->satisfySkillRequire(pSkillInfo); if (param.bMagicHitRoll) { bHitRoll = HitRoll::isSuccessMagic(pOusters, pSkillInfo, pOustersSkillSlot, HitBonus); } else { bHitRoll = HitRoll::isSuccess(pOusters, pTargetCreature); } ZoneCoord_t X = pOusters->getX(); ZoneCoord_t Y = pOusters->getY(); ZoneCoord_t targetX = pTargetCreature->getX(); ZoneCoord_t targetY = pTargetCreature->getY(); if (bManaCheck && bTimeCheck && bRangeCheck && bHitRoll && bCanHit && bPK && bSatisfyRequire ) { decreaseMana(pOusters, RequiredMP, _GCSkillToObjectOK1); bool bCanSeeCaster = canSee(pTargetCreature, pOusters); if (bCanSeeCaster) { setDamage(pTargetCreature, Damage, pOusters, param.SkillType, &_GCSkillToObjectOK2, &_GCSkillToObjectOK1); computeAlignmentChange(pTargetCreature, Damage, pOusters, &_GCSkillToObjectOK2, &_GCSkillToObjectOK1); decreaseDurability(pOusters, pTargetCreature, pSkillInfo, &_GCSkillToObjectOK1, &_GCSkillToObjectOK2); } else { setDamage(pTargetCreature, Damage, pOusters, param.SkillType, &_GCSkillToObjectOK6, &_GCSkillToObjectOK1); computeAlignmentChange(pTargetCreature, Damage, pOusters, &_GCSkillToObjectOK6, &_GCSkillToObjectOK1); decreaseDurability(pOusters, pTargetCreature, pSkillInfo, &_GCSkillToObjectOK1, &_GCSkillToObjectOK6); } if (pTargetCreature->isDead()) { int exp = computeCreatureExp(pTargetCreature, 100, pOusters); shareOustersExp(pOusters, exp, _GCSkillToObjectOK1); } increaseAlignment(pOusters, pTargetCreature, _GCSkillToObjectOK1); _GCSkillToObjectOK1.setSkillType(param.SkillType); _GCSkillToObjectOK1.setCEffectID(CEffectID); _GCSkillToObjectOK1.setTargetObjectID(TargetObjectID); _GCSkillToObjectOK1.setDuration(0); _GCSkillToObjectOK1.setGrade(param.Grade); _GCSkillToObjectOK2.setObjectID(pOusters->getObjectID()); _GCSkillToObjectOK2.setSkillType(param.SkillType); _GCSkillToObjectOK2.setDuration(0); _GCSkillToObjectOK2.setGrade(param.Grade); _GCSkillToObjectOK3.setObjectID(pOusters->getObjectID()); _GCSkillToObjectOK3.setSkillType(param.SkillType); _GCSkillToObjectOK3.setTargetXY(targetX, targetY); _GCSkillToObjectOK3.setGrade(param.Grade); _GCSkillToObjectOK4.setSkillType(param.SkillType); _GCSkillToObjectOK4.setTargetObjectID(TargetObjectID); _GCSkillToObjectOK4.setGrade(param.Grade); _GCSkillToObjectOK5.setObjectID(pOusters->getObjectID()); _GCSkillToObjectOK5.setTargetObjectID(TargetObjectID); _GCSkillToObjectOK5.setSkillType(param.SkillType); _GCSkillToObjectOK5.setGrade(param.Grade); _GCSkillToObjectOK6.setXY(X, Y); _GCSkillToObjectOK6.setSkillType(param.SkillType); _GCSkillToObjectOK6.setDuration(0); _GCSkillToObjectOK6.setGrade(param.Grade); pPlayer->sendPacket(&_GCSkillToObjectOK1); Player* pTargetPlayer = NULL; if (pTargetCreature->isPC()) { pTargetPlayer = pTargetCreature->getPlayer(); Assert(pTargetPlayer != NULL); if (bCanSeeCaster) pTargetPlayer->sendPacket(&_GCSkillToObjectOK2); else pTargetPlayer->sendPacket(&_GCSkillToObjectOK6); } else { Monster* pMonster = dynamic_cast<Monster*>(pTargetCreature); pMonster->addEnemy(pOusters); } list<Creature*> cList; cList.push_back(pOusters); cList.push_back(pTargetCreature); cList = pZone->broadcastSkillPacket(X, Y, targetX, targetY, &_GCSkillToObjectOK5, cList); pZone->broadcastPacket(X, Y, &_GCSkillToObjectOK3 , cList); pZone->broadcastPacket(targetX, targetY, &_GCSkillToObjectOK4 , cList); pOustersSkillSlot->setRunTime(param.Delay); result.bSuccess = true; } else { executeSkillFailNormal(pOusters, param.SkillType, pTargetCreature, param.Grade); } } catch (Throwable & t) { executeSkillFailException(pOusters, param.SkillType, param.Grade); } __END_CATCH }
void SimpleMissileSkill::execute( Slayer* pSlayer, ObjectID_t TargetObjectID, SkillSlot* pSkillSlot, const SIMPLE_SKILL_INPUT& param, SIMPLE_SKILL_OUTPUT& result, CEffectID_t CEffectID) throw(Error) { __BEGIN_TRY Assert(pSlayer != NULL); Assert(pSkillSlot != NULL); try { Player* pPlayer = pSlayer->getPlayer(); Zone* pZone = pSlayer->getZone(); Assert(pPlayer != NULL); Assert(pZone != NULL); Creature* pTargetCreature = pZone->getCreature(TargetObjectID); //Assert(pTargetCreature != NULL); // NPC는 공격할 수가 없다. // NoSuch제거. by sigi. 2002.5.2 if (pTargetCreature==NULL || !canAttack(pSlayer, pTargetCreature ) || pTargetCreature->isNPC()) { executeSkillFailException(pSlayer, param.SkillType); return; } result.pTargetCreature = pTargetCreature; GCSkillToObjectOK1 _GCSkillToObjectOK1; GCSkillToObjectOK2 _GCSkillToObjectOK2; GCSkillToObjectOK3 _GCSkillToObjectOK3; GCSkillToObjectOK4 _GCSkillToObjectOK4; GCSkillToObjectOK5 _GCSkillToObjectOK5; SkillInfo* pSkillInfo = g_pSkillInfoManager->getSkillInfo(param.SkillType); SkillDomainType_t DomainType = pSkillInfo->getDomainType(); SkillLevel_t SkillLevel = pSkillSlot->getExpLevel(); bool bCriticalHit = false; Damage_t Damage = 0; if (param.bAdd) { // 파라미터로 전달된 데미지 값이 더해지는 데미지라면, // 일반 데미지를 계산 후, 데미지를 더해야 한다. // 파라미터로 전달된 데미지 값이 직접적으로 쓰이는 데미지라면, // 이 부분까지 들어오지 않으므로, 밑의 부분까지 0으로 전달된다. Damage += computeDamage(pSlayer, pTargetCreature, SkillLevel/5, bCriticalHit); } if (param.bMagicDamage) { // 만일 스킬 데미지가 마법 데미지라면, 마법 데미지 계산 함수를 이용해 계산을 해준다. Damage += computeMagicDamage(pTargetCreature, param.SkillDamage, param.SkillType); } else { Damage += param.SkillDamage; } ZoneCoord_t myX = pSlayer->getX(); ZoneCoord_t myY = pSlayer->getY(); ZoneCoord_t targetX = pTargetCreature->getX(); ZoneCoord_t targetY = pTargetCreature->getY(); int RequiredMP = (int)pSkillInfo->getConsumeMP(); bool bManaCheck = hasEnoughMana(pSlayer, RequiredMP); bool bTimeCheck = verifyRunTime(pSkillSlot); bool bRangeCheck = verifyDistance(pSlayer, pTargetCreature, pSkillInfo->getRange()); bool bHitRoll = false; bool bPK = verifyPK(pSlayer, pTargetCreature); if (param.bMagicHitRoll) { bHitRoll = HitRoll::isSuccessMagic(pSlayer, pSkillInfo, pSkillSlot); } else { bHitRoll = HitRoll::isSuccess(pSlayer, pTargetCreature, SkillLevel/2); } if (bManaCheck && bTimeCheck && bRangeCheck && bHitRoll && bPK) { decreaseMana(pSlayer, RequiredMP, _GCSkillToObjectOK1); // 데미지를 가하고, 내구도를 떨어뜨린다. setDamage(pTargetCreature, Damage, pSlayer, param.SkillType, &_GCSkillToObjectOK2, &_GCSkillToObjectOK1); computeAlignmentChange(pTargetCreature, Damage, pSlayer, &_GCSkillToObjectOK2, &_GCSkillToObjectOK1); decreaseDurability(pSlayer, pTargetCreature, NULL, &_GCSkillToObjectOK1, &_GCSkillToObjectOK2); // 타겟이 슬레이어가 아닌 경우에만 경험치를 올려준다. if (!pTargetCreature->isSlayer()) { shareAttrExp(pSlayer, Damage , param.STRMultiplier, param.DEXMultiplier, param.INTMultiplier, _GCSkillToObjectOK1); increaseDomainExp(pSlayer, DomainType, pSkillInfo->getPoint(), _GCSkillToObjectOK1, pTargetCreature->getLevel()); increaseSkillExp(pSlayer, DomainType, pSkillSlot, pSkillInfo, _GCSkillToObjectOK1); increaseAlignment(pSlayer, pTargetCreature, _GCSkillToObjectOK1); } _GCSkillToObjectOK1.setSkillType(param.SkillType); _GCSkillToObjectOK1.setCEffectID(CEffectID); _GCSkillToObjectOK1.setTargetObjectID(TargetObjectID); _GCSkillToObjectOK1.setDuration(0); _GCSkillToObjectOK2.setObjectID(pSlayer->getObjectID()); _GCSkillToObjectOK2.setSkillType(param.SkillType); _GCSkillToObjectOK2.setDuration(0); _GCSkillToObjectOK3.setObjectID(pSlayer->getObjectID()); _GCSkillToObjectOK3.setSkillType(param.SkillType); _GCSkillToObjectOK3.setTargetXY(targetX, targetY); _GCSkillToObjectOK4.setSkillType(param.SkillType); _GCSkillToObjectOK4.setTargetObjectID(TargetObjectID); _GCSkillToObjectOK5.setObjectID(pSlayer->getObjectID()); _GCSkillToObjectOK5.setTargetObjectID(TargetObjectID); _GCSkillToObjectOK5.setSkillType(param.SkillType); _GCSkillToObjectOK5.setDuration(0); // Send Packet pPlayer->sendPacket(&_GCSkillToObjectOK1); if (pTargetCreature->isPC()) { Player* pTargetPlayer = pTargetCreature->getPlayer(); Assert(pTargetPlayer != NULL); pTargetPlayer->sendPacket(&_GCSkillToObjectOK2); } else if (pTargetCreature->isMonster()) { Monster* pMonster = dynamic_cast<Monster*>(pTargetCreature); pMonster->addEnemy(pSlayer); } list<Creature*> cList; cList.push_back(pSlayer); cList.push_back(pTargetCreature); cList = pZone->broadcastSkillPacket(myX, myY, targetX, targetY, &_GCSkillToObjectOK5, cList); pZone->broadcastPacket(myX, myY, &_GCSkillToObjectOK3 , cList); pZone->broadcastPacket(targetX, targetY, &_GCSkillToObjectOK4 , cList); pSkillSlot->setRunTime(param.Delay); result.bSuccess = true; } else { executeSkillFailNormal(pSlayer, param.SkillType, pTargetCreature); } } catch (Throwable & t) { executeSkillFailException(pSlayer, param.SkillType); } __END_CATCH }
void SimpleMissileSkill::execute( Vampire* pVampire, ObjectID_t TargetObjectID, VampireSkillSlot* pVampireSkillSlot, const SIMPLE_SKILL_INPUT& param, SIMPLE_SKILL_OUTPUT& result, CEffectID_t CEffectID, int HitBonus) throw(Error) { __BEGIN_TRY Assert(pVampire != NULL); Assert(pVampireSkillSlot != NULL); try { Player* pPlayer = pVampire->getPlayer(); Zone* pZone = pVampire->getZone(); Assert(pPlayer != NULL); Assert(pZone != NULL); Creature* pTargetCreature = pZone->getCreature(TargetObjectID); //Assert(pTargetCreature != NULL); // NPC는 공격할 수가 없다. // NoSuch제거. by sigi. 2002.5.2 if (pTargetCreature==NULL || !canAttack(pVampire, pTargetCreature ) || pTargetCreature->isNPC()) { executeSkillFailException(pVampire, param.SkillType); return; } result.pTargetCreature = pTargetCreature; GCSkillToObjectOK1 _GCSkillToObjectOK1; GCSkillToObjectOK2 _GCSkillToObjectOK2; GCSkillToObjectOK3 _GCSkillToObjectOK3; GCSkillToObjectOK4 _GCSkillToObjectOK4; GCSkillToObjectOK5 _GCSkillToObjectOK5; GCSkillToObjectOK6 _GCSkillToObjectOK6; SkillInfo* pSkillInfo = g_pSkillInfoManager->getSkillInfo(param.SkillType); bool bCriticalHit = false; Damage_t Damage = 0; if (param.bAdd) { // 파라미터로 전달된 데미지 값이 더해지는 데미지라면, // 일반 데미지를 계산 후, 데미지를 더해야 한다. // 파라미터로 전달된 데미지 값이 직접적으로 쓰이는 데미지라면, // 이 부분까지 들어오지 않으므로, 밑의 부분까지 0으로 전달된다. Damage += computeDamage(pVampire, pTargetCreature, 0, bCriticalHit); } if (param.bMagicDamage) { // 만일 스킬 데미지가 마법 데미지라면, 마법 데미지 계산 함수를 이용해 계산을 해준다. Damage += computeMagicDamage(pTargetCreature, param.SkillDamage, param.SkillType, true, pVampire); } else { Damage += param.SkillDamage; } int RequiredMP = decreaseConsumeMP(pVampire, pSkillInfo); bool bManaCheck = hasEnoughMana(pVampire, RequiredMP); bool bTimeCheck = verifyRunTime(pVampireSkillSlot); bool bRangeCheck = verifyDistance(pVampire, pTargetCreature, pSkillInfo->getRange()); bool bHitRoll = false; bool bCanHit = canHit(pVampire, pTargetCreature, param.SkillType); bool bPK = verifyPK(pVampire, pTargetCreature); if (param.bMagicHitRoll) { bHitRoll = HitRoll::isSuccessMagic(pVampire, pSkillInfo, pVampireSkillSlot, HitBonus); } else { bHitRoll = HitRoll::isSuccess(pVampire, pTargetCreature); } ZoneCoord_t vampX = pVampire->getX(); ZoneCoord_t vampY = pVampire->getY(); ZoneCoord_t targetX = pTargetCreature->getX(); ZoneCoord_t targetY = pTargetCreature->getY(); if (bManaCheck && bTimeCheck && bRangeCheck && bHitRoll && bCanHit && bPK) { decreaseMana(pVampire, RequiredMP, _GCSkillToObjectOK1); bool bCanSeeCaster = canSee(pTargetCreature, pVampire); // 데미지를 가하고, 아이템 내구도를 떨어뜨린다. if (bCanSeeCaster) { setDamage(pTargetCreature, Damage, pVampire, param.SkillType, &_GCSkillToObjectOK2, &_GCSkillToObjectOK1); computeAlignmentChange(pTargetCreature, Damage, pVampire, &_GCSkillToObjectOK2, &_GCSkillToObjectOK1); decreaseDurability(pVampire, pTargetCreature, pSkillInfo, &_GCSkillToObjectOK1, &_GCSkillToObjectOK2); } else { setDamage(pTargetCreature, Damage, pVampire, param.SkillType, &_GCSkillToObjectOK6, &_GCSkillToObjectOK1); computeAlignmentChange(pTargetCreature, Damage, pVampire, &_GCSkillToObjectOK6, &_GCSkillToObjectOK1); decreaseDurability(pVampire, pTargetCreature, pSkillInfo, &_GCSkillToObjectOK1, &_GCSkillToObjectOK6); } // 상대가 죽었다면 경험치를 좀 올려준다. if (pTargetCreature->isDead()) { int exp = computeCreatureExp(pTargetCreature, KILL_EXP); shareVampExp(pVampire, exp, _GCSkillToObjectOK1); } increaseAlignment(pVampire, pTargetCreature, _GCSkillToObjectOK1); _GCSkillToObjectOK1.setSkillType(param.SkillType); _GCSkillToObjectOK1.setCEffectID(CEffectID); _GCSkillToObjectOK1.setTargetObjectID(TargetObjectID); _GCSkillToObjectOK1.setDuration(0); _GCSkillToObjectOK2.setObjectID(pVampire->getObjectID()); _GCSkillToObjectOK2.setSkillType(param.SkillType); _GCSkillToObjectOK2.setDuration(0); _GCSkillToObjectOK3.setObjectID(pVampire->getObjectID()); _GCSkillToObjectOK3.setSkillType(param.SkillType); _GCSkillToObjectOK3.setTargetXY(targetX, targetY); _GCSkillToObjectOK4.setSkillType(param.SkillType); _GCSkillToObjectOK4.setTargetObjectID(TargetObjectID); _GCSkillToObjectOK5.setObjectID(pVampire->getObjectID()); _GCSkillToObjectOK5.setTargetObjectID(TargetObjectID); _GCSkillToObjectOK5.setSkillType(param.SkillType); _GCSkillToObjectOK6.setXY(vampX, vampY); _GCSkillToObjectOK6.setSkillType(param.SkillType); _GCSkillToObjectOK6.setDuration(0); pPlayer->sendPacket(&_GCSkillToObjectOK1); Player* pTargetPlayer = NULL; if (pTargetCreature->isPC()) { pTargetPlayer = pTargetCreature->getPlayer(); Assert(pTargetPlayer != NULL); if (bCanSeeCaster) pTargetPlayer->sendPacket(&_GCSkillToObjectOK2); else pTargetPlayer->sendPacket(&_GCSkillToObjectOK6); } else { Monster* pMonster = dynamic_cast<Monster*>(pTargetCreature); pMonster->addEnemy(pVampire); } list<Creature*> cList; cList.push_back(pVampire); cList.push_back(pTargetCreature); cList = pZone->broadcastSkillPacket(vampX, vampY, targetX, targetY, &_GCSkillToObjectOK5, cList); pZone->broadcastPacket(vampX, vampY, &_GCSkillToObjectOK3 , cList); pZone->broadcastPacket(targetX, targetY, &_GCSkillToObjectOK4 , cList); pVampireSkillSlot->setRunTime(param.Delay); result.bSuccess = true; } else { executeSkillFailNormal(pVampire, param.SkillType, pTargetCreature); } } catch (Throwable & t) { executeSkillFailException(pVampire, param.SkillType); } __END_CATCH }
////////////////////////////////////////////////////////////////////////////// // 슬레이어 오브젝트 핸들러 ////////////////////////////////////////////////////////////////////////////// void ProtectionFromAcid::execute(Slayer* pSlayer, ObjectID_t TargetObjectID, SkillSlot* pSkillSlot, CEffectID_t CEffectID) throw(Error) { __BEGIN_TRY //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << "begin " << endl; Assert(pSlayer != NULL); Assert(pSkillSlot != NULL); try { Player* pPlayer = pSlayer->getPlayer(); Zone* pZone = pSlayer->getZone(); Assert(pPlayer != NULL); Assert(pZone != NULL); Creature* pTargetCreature = pZone->getCreature(TargetObjectID); //Assert(pTargetCreature != NULL); // NoSuch제거. by sigi. 2002.5.2 if (pTargetCreature==NULL || !pTargetCreature->isSlayer() ) { executeSkillFailException(pSlayer, getSkillType()); //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " end " << endl; return; } GCSkillToObjectOK1 _GCSkillToObjectOK1; GCSkillToObjectOK2 _GCSkillToObjectOK2; GCSkillToObjectOK5 _GCSkillToObjectOK5; SkillType_t SkillType = pSkillSlot->getSkillType(); SkillInfo* pSkillInfo = g_pSkillInfoManager->getSkillInfo(SkillType); SkillDomainType_t DomainType = pSkillInfo->getDomainType(); int RequiredMP = (int)pSkillInfo->getConsumeMP(); bool bManaCheck = hasEnoughMana(pSlayer, RequiredMP); bool bTimeCheck = verifyRunTime(pSkillSlot); bool bRangeCheck = verifyDistance(pSlayer, pTargetCreature, pSkillInfo->getRange()); bool bHitRoll = HitRoll::isSuccessMagic(pSlayer, pSkillInfo, pSkillSlot); bool bEffected = pTargetCreature->isFlag(Effect::EFFECT_CLASS_PROTECTION_FROM_ACID); if (bManaCheck && bTimeCheck && bRangeCheck && bHitRoll && !bEffected) { // 마나를 줄인다. decreaseMana(pSlayer, RequiredMP, _GCSkillToObjectOK1); // 경험치를 올려준다. SkillGrade Grade = g_pSkillInfoManager->getGradeByDomainLevel(pSlayer->getSkillDomainLevel(DomainType)); Exp_t ExpUp = 10* (Grade + 1); shareAttrExp(pSlayer, ExpUp, 1, 1, 8, _GCSkillToObjectOK1); increaseDomainExp(pSlayer, DomainType, pSkillInfo->getPoint(), _GCSkillToObjectOK1); increaseSkillExp(pSlayer, DomainType, pSkillSlot, pSkillInfo, _GCSkillToObjectOK1); // 이펙트의 효과와 지속시간을 계산한다. SkillInput input(pSlayer, pSkillSlot); SkillOutput output; input.TargetType = SkillInput::TARGET_OTHER; computeOutput(input, output); // 이펙트를 생성해서 붙인다. EffectProtectionFromAcid* pEPFP = new EffectProtectionFromAcid (pTargetCreature); Assert(pEPFP != NULL); pEPFP->setDeadline(output.Duration); pEPFP->setResist(output.Damage); pTargetCreature->addEffect(pEPFP); pTargetCreature->setFlag(Effect::EFFECT_CLASS_PROTECTION_FROM_ACID); if (pTargetCreature->isSlayer()) { Slayer* pTargetSlayer = dynamic_cast<Slayer*>(pTargetCreature); SLAYER_RECORD prev; pTargetSlayer->getSlayerRecord(prev); pTargetSlayer->initAllStat(); pTargetSlayer->addModifyInfo(prev, _GCSkillToObjectOK1); } else { Assert(false); } // 패킷을 준비해서 보낸다. _GCSkillToObjectOK1.setSkillType(SkillType); _GCSkillToObjectOK1.setCEffectID(CEffectID); _GCSkillToObjectOK1.setTargetObjectID(TargetObjectID); _GCSkillToObjectOK1.setDuration(output.Duration); _GCSkillToObjectOK2.setObjectID(pSlayer->getObjectID()); _GCSkillToObjectOK2.setSkillType(SkillType); _GCSkillToObjectOK2.setDuration (output.Duration); _GCSkillToObjectOK5.setObjectID(pSlayer->getObjectID()); _GCSkillToObjectOK5.setSkillType(SkillType); _GCSkillToObjectOK5.setTargetObjectID (TargetObjectID); _GCSkillToObjectOK5.setDuration (output.Duration); // Send Packet pPlayer->sendPacket(&_GCSkillToObjectOK1); if (pSlayer != pTargetCreature && pTargetCreature->isPC()) { Player* pTargetPlayer = pTargetCreature->getPlayer(); Assert(pTargetPlayer != NULL); pTargetPlayer->sendPacket(&_GCSkillToObjectOK2); } list<Creature*> cList; cList.push_back(pSlayer); cList.push_back(pTargetCreature); pZone->broadcastPacket(pSlayer->getX(), pSlayer->getY(), &_GCSkillToObjectOK5 , cList); // 이펙트가 붙었다고 알려준다. GCAddEffect gcAddEffect; gcAddEffect.setObjectID(pTargetCreature->getObjectID()); gcAddEffect.setEffectID(Effect::EFFECT_CLASS_PROTECTION_FROM_ACID); gcAddEffect.setDuration(output.Duration); pZone->broadcastPacket(pTargetCreature->getX(), pTargetCreature->getY(), &gcAddEffect); pSkillSlot->setRunTime(output.Delay); } else { executeSkillFailNormal(pSlayer, getSkillType(), pTargetCreature); } } catch (Throwable & t) { executeSkillFailException(pSlayer, getSkillType()); } //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " end " << endl; __END_CATCH }
////////////////////////////////////////////////////////////////////////////// // 뱀파이어 오브젝트 핸들러 ////////////////////////////////////////////////////////////////////////////// void Transfusion::execute(Vampire* pVampire, ObjectID_t TargetObjectID, VampireSkillSlot* pVampireSkillSlot, CEffectID_t CEffectID) throw(Error) { __BEGIN_TRY //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << "begin " << endl; Assert(pVampire != NULL); Assert(pVampireSkillSlot != NULL); //cout << "Transfusion" << endl; try { Zone* pZone = pVampire->getZone(); Assert(pZone != NULL); Creature* pTargetCreature = pZone->getCreature(TargetObjectID); //Assert(pTargetCreature != NULL); // NPC는 공격할 수가 없다. // NoSuch제거. by sigi. 2002.5.2 if (pTargetCreature==NULL || pTargetCreature->isNPC() // HIDE 인 놈은 되살려내면 이상하게 된다. 일단 막아놓음. // 2003. 1. 17. DEW || pTargetCreature->isFlag(Effect::EFFECT_CLASS_HIDE) || (g_pConfig->hasKey("Hardcore") && g_pConfig->getPropertyInt("Hardcore")!=0 && pTargetCreature->isDead() ) ) { executeSkillFailException(pVampire, getSkillType()); //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " end " << endl; return; } ZoneCoord_t X = pTargetCreature->getX(); ZoneCoord_t Y = pTargetCreature->getY(); GCSkillToTileOK1 _GCSkillToTileOK1; GCSkillToTileOK2 _GCSkillToTileOK2; GCSkillToTileOK3 _GCSkillToTileOK3; GCSkillToTileOK4 _GCSkillToTileOK4; GCSkillToTileOK5 _GCSkillToTileOK5; GCSkillToTileOK6 _GCSkillToTileOK6; SkillType_t SkillType = pVampireSkillSlot->getSkillType(); SkillInfo* pSkillInfo = g_pSkillInfoManager->getSkillInfo(SkillType); // Knowledge of Innate 가 있다면 hit bonus 10 int HitBonus = 0; if (pVampire->hasRankBonus(RankBonus::RANK_BONUS_KNOWLEDGE_OF_INNATE ) ) { RankBonus* pRankBonus = pVampire->getRankBonus(RankBonus::RANK_BONUS_KNOWLEDGE_OF_INNATE); Assert(pRankBonus != NULL); HitBonus = pRankBonus->getPoint(); } // 15%를 사용 int CurrentHP = pVampire->getHP(ATTR_CURRENT); #ifdef __CHINA_SERVER__ int RequiredMP = CurrentHP*15/100; //decreaseConsumeMP(pVampire, pSkillInfo); int RecoverHP = CurrentHP*17/100; #else int RequiredMP = CurrentHP*12/100; //decreaseConsumeMP(pVampire, pSkillInfo); int RecoverHP = CurrentHP*12/100; #endif //bool bManaCheck = hasEnoughMana(pVampire, RequiredMP); bool bTimeCheck = verifyRunTime(pVampireSkillSlot); bool bRangeCheck = verifyDistance(pVampire, X, Y, pSkillInfo->getRange()); bool bHitRoll = HitRoll::isSuccessMagic(pVampire, pSkillInfo, pVampireSkillSlot, HitBonus); bool bHPCheck = false; Range_t Range = 1; // 상대방의 HP가 Full이 아니고 // 자신의 HP가 30이상 if (pVampire->getHP(ATTR_CURRENT) >= 30) { if (pTargetCreature->isVampire()) { Vampire* pTargetVampire = dynamic_cast<Vampire*>(pTargetCreature); // 현재HP+SilverDamage < MaxHP 여야 한다. if (pTargetVampire->getHP(ATTR_CURRENT) + pTargetVampire->getSilverDamage() < pTargetVampire->getHP(ATTR_MAX)) bHPCheck = true; } /* // 아직 이건 필요없다. else if (pTargetCreature->isMonster()) { Monster* pMonster = dynamic_cast<Monster*>(pTargetCreature); if (pMonster->getHP(ATTR_MAX) < pMonster->getHP(ATTR_MAX_HP)) bHPCHeck = true; } */ } if (bTimeCheck && bRangeCheck && bHitRoll && bHPCheck) { //cout << "Transfusion Success" << endl; decreaseMana(pVampire, RequiredMP, _GCSkillToTileOK1); // 데미지와 지속 시간을 계산한다. SkillInput input(pVampire); SkillOutput output; computeOutput(input, output); // TargetCreature의 HP를 채운다 if (pTargetCreature->isVampire()) { Vampire* pTargetVampire = dynamic_cast<Vampire*>(pTargetCreature); HP_t maxHP = pTargetVampire->getHP(ATTR_MAX); HP_t currentHP = pTargetVampire->getHP(ATTR_CURRENT); HP_t newHP = min((int)maxHP, currentHP + RecoverHP); pTargetVampire->setHP(newHP); // HP가 30%가 되면(33% -_-;) 살아나게 된다. if (pTargetCreature->isFlag(Effect::EFFECT_CLASS_COMA)) { //cout << "Target has EFFECT_COMA" << endl; if (newHP*3 >= maxHP) { //cout << "Target HP is over 1/3" << endl; EffectComa* pEffectComa = (EffectComa*)(pTargetCreature->findEffect(Effect::EFFECT_CLASS_COMA)); Assert(pEffectComa != NULL); if (pEffectComa->canResurrect()) { //cout << "Can Resurrect!" << endl; // 타겟의 이펙트 매니저에서 코마 이펙트를 삭제한다. pTargetCreature->deleteEffect(Effect::EFFECT_CLASS_COMA); pTargetCreature->removeFlag(Effect::EFFECT_CLASS_COMA); // 코마 이펙트가 날아갔다고 알려준다. GCRemoveEffect gcRemoveEffect; gcRemoveEffect.setObjectID(pTargetCreature->getObjectID()); gcRemoveEffect.addEffectList((EffectID_t)Effect::EFFECT_CLASS_COMA); pZone->broadcastPacket(pTargetCreature->getX(), pTargetCreature->getY(), &gcRemoveEffect); // 이펙트 정보를 다시 보내준다. by sigi. 2002.11.14 pTargetCreature->getEffectManager()->sendEffectInfo(pTargetCreature, pZone, pTargetCreature->getX(), pTargetCreature->getY()); // EffectKillAftermath 를 붙인다. if (pTargetCreature->isFlag(Effect::EFFECT_CLASS_KILL_AFTERMATH)) { Effect *pEffect = pTargetCreature->findEffect(Effect::EFFECT_CLASS_KILL_AFTERMATH); EffectKillAftermath* pEffectKillAftermath = dynamic_cast<EffectKillAftermath*>(pEffect); pEffectKillAftermath->setDeadline(5*600); } else { EffectKillAftermath* pEffectKillAftermath = new EffectKillAftermath(pTargetCreature); pEffectKillAftermath->setDeadline(5*600); pTargetCreature->addEffect(pEffectKillAftermath); pTargetCreature->setFlag(Effect::EFFECT_CLASS_KILL_AFTERMATH); pEffectKillAftermath->create(pTargetCreature->getName()); } } } } // 주위에 체력이 채워졌다는 사실을 알린다. GCStatusCurrentHP gcStatusCurrentHP; gcStatusCurrentHP.setObjectID(pTargetVampire->getObjectID()); gcStatusCurrentHP.setCurrentHP(pTargetVampire->getHP(ATTR_CURRENT)); pZone->broadcastPacket(X, Y, &gcStatusCurrentHP); // 자신의 에너지가 줄어든것도 보여주자 gcStatusCurrentHP.setObjectID(pVampire->getObjectID()); gcStatusCurrentHP.setCurrentHP(pVampire->getHP(ATTR_CURRENT)); pZone->broadcastPacket(pVampire->getX(), pVampire->getY(), &gcStatusCurrentHP); } ZoneCoord_t myX = pVampire->getX(); ZoneCoord_t myY = pVampire->getY(); _GCSkillToTileOK1.setSkillType(SkillType); _GCSkillToTileOK1.setCEffectID(CEffectID); _GCSkillToTileOK1.setX(X); _GCSkillToTileOK1.setY(Y); _GCSkillToTileOK1.setDuration(output.Duration); _GCSkillToTileOK1.setRange(Range); _GCSkillToTileOK2.setSkillType(SkillType); _GCSkillToTileOK2.setObjectID(pVampire->getObjectID()); _GCSkillToTileOK2.setX(X); _GCSkillToTileOK2.setY(Y); _GCSkillToTileOK2.setDuration(output.Duration); _GCSkillToTileOK2.setRange(Range); _GCSkillToTileOK3.setObjectID(pVampire->getObjectID()); _GCSkillToTileOK3.setSkillType(SkillType); _GCSkillToTileOK3.setX(X); _GCSkillToTileOK3.setY(Y); _GCSkillToTileOK4.setSkillType(SkillType); _GCSkillToTileOK4.setX(X); _GCSkillToTileOK4.setY(Y); _GCSkillToTileOK4.setDuration(output.Duration); _GCSkillToTileOK4.setRange(Range); _GCSkillToTileOK5.setObjectID(pVampire->getObjectID()); _GCSkillToTileOK5.setSkillType(SkillType); _GCSkillToTileOK5.setX(X); _GCSkillToTileOK5.setY(Y); _GCSkillToTileOK5.setDuration(output.Duration); _GCSkillToTileOK5.setRange(Range); Player* pPlayer = pVampire->getPlayer(); Assert(pPlayer != NULL); pPlayer->sendPacket(&_GCSkillToTileOK1); list<Creature*> cList; cList.push_back(pVampire); cList = pZone->broadcastSkillPacket(myX, myY, X, Y, &_GCSkillToTileOK5, cList); pZone->broadcastPacket(myX, myY, &_GCSkillToTileOK3 , cList); pZone->broadcastPacket(X, Y, &_GCSkillToTileOK4 , cList); pVampireSkillSlot->setRunTime(output.Delay); } else { //cout << "Transfusion Failed" << endl; executeSkillFailNormal(pVampire, getSkillType(), NULL); } } catch (Throwable & t) { //cout << "Transfusion Failed2" << endl; executeSkillFailException(pVampire, getSkillType()); } //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " end " << endl; __END_CATCH }