//---------------------------------------------------------------------- // affect //---------------------------------------------------------------------- void EffectTransportCreature::affect(Creature* pCreature) throw(Error) { __BEGIN_TRY Timeval nextTime = getNextTime(); Timeval deadLine = getDeadline(); Turn_t RemainTime = deadLine.tv_sec - nextTime.tv_sec; // StringStream msg; // msg << (int)RemainTime << "초 후에 " << m_ZoneName << "로 이동됩니다."; char msg[50]; sprintf(msg, g_pStringPool->c_str(STRID_TRANSPORT_CREATURE ), (int)RemainTime, m_ZoneName.c_str()); string sMsg(msg); GCSystemMessage gcSystemMessage; gcSystemMessage.setMessage(sMsg); pCreature->getPlayer()->sendPacket(&gcSystemMessage); setNextTime(m_MessageTick); __END_CATCH }
void EffectBlazeWalk::affect(Creature* pCreature) throw(Error) { __BEGIN_TRY Assert(pCreature != NULL); Zone* pZone = pCreature->getZone(); Assert(pZone != NULL); Creature* pAttacker = pZone->getCreature(m_UserObjectID); if (pAttacker == NULL ) { setDeadline(0); return; } if (!(pZone->getZoneLevel() & COMPLETE_SAFE_ZONE) && !pCreature->isDead() && !pCreature->isFlag(Effect::EFFECT_CLASS_COMA ) // 무적상태 체크. by sigi. 2002.9.5 && canAttack(pAttacker, pCreature ) ) { GCModifyInformation gcMI, gcAttackerMI; setDamage(pCreature, m_Point, pAttacker, m_SkillType, &gcMI, &gcAttackerMI); if (pAttacker->isPC() ) computeAlignmentChange(pCreature, m_Point, pAttacker, &gcMI, &gcAttackerMI); if (pCreature->isPC() ) pCreature->getPlayer()->sendPacket(&gcMI); if (pAttacker->isSlayer() && !pCreature->isSlayer() ) { Slayer* pSlayer = dynamic_cast<Slayer*>(pAttacker); if (pSlayer != NULL ) { GCModifyInformation gcMI; shareAttrExp(pSlayer, m_Point, 8, 1, 1, gcAttackerMI); } } if (pAttacker->isPC() ) pAttacker->getPlayer()->sendPacket(&gcAttackerMI); if (pCreature->isDead() ) setDeadline(0); } m_AttackNum--; if (m_AttackNum > 0 ) { setNextTime(5); } else setDeadline(0); //cout << "EffectBlazeWalk " << "begin" << endl; //cout << "EffectBlazeWalk " << "end" << endl; __END_CATCH }
void EffectArmageddon::affect(Creature* pCreature) throw(Error) { __BEGIN_TRY Assert(pCreature != NULL); Zone* pZone = pCreature->getZone(); Assert(pZone != NULL); // 이펙트를 건 크리쳐를 가져온다. // !! 이미 존을 떠났을 수도 있으므로 NULL 이 될 수 있다. // by bezz. 2003.1.4 //Creature* pCastCreature = pZone->getCreature(m_UserObjectID); //ZoneCoord_t X = pCreature->getX(); //ZoneCoord_t Y = pCreature->getY(); //if (pCreature->isFlag(Effect::EFFECT_CLASS_NO_DAMAGE ) ) //{ // return; //} //cout << "EffectArmageddon affect damage :" << m_Damage << endl; // 매초 데미지 주는거 잠시 막아놓음. by Sequoia /*if (pCreature->isSlayer() ) { Slayer* pSlayer = dynamic_cast<Slayer*>(pCreature); GCModifyInformation gcMI; ::setDamage(pSlayer, m_Damage, pCastCreature, SKILL_ARMAGEDDON, &gcMI); pSlayer->getPlayer()->sendPacket(&gcMI); } else if (pCreature->isVampire() ) { Vampire* pVampire = dynamic_cast<Vampire*>(pCreature); GCModifyInformation gcMI; ::setDamage(pVampire, m_Damage, pCastCreature, SKILL_ARMAGEDDON, &gcMI); pVampire->getPlayer()->sendPacket(&gcMI); } else if (pCreature->isMonster() ) { Monster* pMonster = dynamic_cast<Monster*>(pCreature); ::setDamage(pMonster, m_Damage, pCastCreature, SKILL_ARMAGEDDON); }*/ setNextTime(m_Delay); __END_CATCH }
void EffectVampireRelic::affect(Creature* pCreature) throw(Error) { __BEGIN_TRY //Timeval nextTime = getNextTime(); //Timeval deadLine = getDeadline(); //Turn_t RemainTime = deadLine.tv_sec - nextTime.tv_sec; /* StringStream msg; if (pCreature->isSlayer()) { Slayer* pSlayer = dynamic_cast<Slayer*>(pCreature); msg << pSlayer->getName(); } else { Vampire* pVampire = dynamic_cast<Vampire*>(pCreature); msg << pVampire->getName(); } msg << " 님이 뱀파이어 성물을 가졌습니다."; */ char msg[50]; sprintf(msg, g_pStringPool->c_str(STRID_TAKE_VAMPIRE_RELIC ), pCreature->getName().c_str()); string sMsg(msg); GCSystemMessage gcSystemMessage; gcSystemMessage.setType(SYSTEM_MESSAGE_COMBAT); gcSystemMessage.setMessage(sMsg); g_pZoneGroupManager->broadcast(&gcSystemMessage); // Effect붙인다. GCAddEffect gcAddEffect; gcAddEffect.setObjectID(pCreature->getObjectID()); gcAddEffect.setEffectID(getSendEffectClass()); gcAddEffect.setDuration(65000); pCreature->getZone()->broadcastPacket(pCreature->getX(), pCreature->getY(), &gcAddEffect); setNextTime(m_Tick); __END_CATCH }
void EffectHalo::affect() throw(Error) { __BEGIN_TRY setNextTime(10); //cout << "EffectHalo" << "affect BEGIN" << endl; Creature* pCreature = m_pZone->getCreature(m_TargetOID); affect(pCreature); __END_CATCH }
void EffectWithWarning::start() { setNextTime(m_SignDuration); setDeadline(m_SignDuration + m_MainDuration); GCAddEffectToTile gcAET; gcAET.setXY(m_X, m_Y); gcAET.setObjectID(getObjectID()); gcAET.setEffectID(m_SignEffect); gcAET.setDuration(m_SignDuration); m_pZone->broadcastPacket(m_X, m_Y, &gcAET); m_State = false; }
void EffectDivineGuidance::affect(Creature* pCreature) throw(Error) { __BEGIN_TRY //cout << "EffectDivineGuidance " << "begin" << endl; //cout << "EffectDivineGuidance " << "end" << endl; Assert(pCreature != NULL); Zone* pZone = pCreature->getZone(); Assert(pZone != NULL); Creature* pAttacker = pZone->getCreature(m_UserObjectID); if (!(pZone->getZoneLevel() & COMPLETE_SAFE_ZONE) && !pCreature->isDead() && !pCreature->isFlag(Effect::EFFECT_CLASS_COMA) // 무적상태 체크. by sigi. 2002.9.5 && canAttack(pAttacker, pCreature ) ) { GCModifyInformation gcMI, gcAttackerMI; setDamage(pCreature, m_Point, pAttacker, SKILL_DIVINE_GUIDANCE, &gcMI, &gcAttackerMI); if (pCreature->isPC() ) pCreature->getPlayer()->sendPacket(&gcMI); if (pAttacker!=NULL) { computeAlignmentChange(pCreature, m_Point, pAttacker, &gcMI, &gcAttackerMI); if (pAttacker->isPC() ) { if (pAttacker->isSlayer() && !pCreature->isSlayer() ) { Slayer* pSlayer = dynamic_cast<Slayer*>(pAttacker); if (pSlayer != NULL ) { GCModifyInformation gcMI; shareAttrExp(pSlayer, m_Point, 1, 1, 8, gcAttackerMI); } } if (pAttacker->isPC() ) pAttacker->getPlayer()->sendPacket(&gcAttackerMI); } } } setNextTime(m_Tick); __END_CATCH }
void EffectMPRecovery::affect() throw(Error) { __BEGIN_TRY // Delay에 따른 체력 회복. setNextTime(m_Delay); Creature* pCreature = dynamic_cast<Creature*>(m_pTarget); affect(pCreature); __END_CATCH }
void EffectAlignmentRecovery::affect() throw(Error) { __BEGIN_TRY setNextTime(m_Delay); Creature* pCreature = dynamic_cast<Creature*>(m_pTarget); Assert(pCreature != NULL); affect(pCreature); __END_CATCH }
////////////////////////////////////////////////////////////////////////////// // constructor ////////////////////////////////////////////////////////////////////////////// Effect::Effect (Zone* pZone , ZoneCoord_t x , ZoneCoord_t y , Object* pTarget , Turn_t delay) throw() { __BEGIN_TRY m_pZone = pZone; m_X = x; m_Y = y; m_pTarget = pTarget; setNextTime(99999999); setDeadline(delay); __END_CATCH }
////////////////////////////////////////////////////////////////////////////// // constructor ////////////////////////////////////////////////////////////////////////////// Effect::Effect () throw() { __BEGIN_TRY m_pZone = NULL; m_X = 0; m_Y = 0; m_pTarget = NULL; m_bBroadcastingEffect = true; setNextTime(99999999); setDeadline(99999999); __END_CATCH }
void TickerTask::exec(){ // execute the task by calling the callback function. // we yield first to do some background tasks in the ESP8266 //Serial.print("execute task "); Serial.println(name); __LOG("execute task "); __LOGLN(name); yield(); // take care of background tasks in the ESP8266 (*Callback)(task_arg); // execute task yield(); // take care of background tasks in the ESP8266 if (tasktype == ONCE){ clear(); // clear the task and mark for deletion return; } // update timing if (!(this->_updated)) // update the scheduling properties if not done yet setNextTime(); this->_updated = false; // clear update flag for next itteration };
//---------------------------------------------------------------------- // constructor //---------------------------------------------------------------------- EffectTransportCreature::EffectTransportCreature (Creature *pCreature, ZoneID_t zoneID , ZoneCoord_t x , ZoneCoord_t y , Turn_t delay) throw(Error) { __BEGIN_TRY Assert(pCreature!=NULL); Assert(pCreature->getZone()!=NULL); m_CreatureID = pCreature->getObjectID(); m_ZoneID = zoneID; m_pZone = pCreature->getZone(); // 그냥 다른 곳에서의 assert때문에 setTarget(pCreature); setDeadline(delay); setNextTime(0); // 서버 전용 Effect이다. by sigi. 2002.11.14 m_bBroadcastingEffect = false; __END_CATCH }
void EffectPKZoneRegen::affect() throw(Error) { __BEGIN_TRY Assert(m_pZone != NULL); Assert(isValidZoneCoord(m_pZone, m_Rect.left, m_Rect.top )); Assert(isValidZoneCoord(m_pZone, m_Rect.right, m_Rect.bottom )); for (ZoneCoord_t X = m_Rect.left ; X <= m_Rect.right ; X++ ) { for (ZoneCoord_t Y = m_Rect.top ; Y <= m_Rect.bottom ; Y++ ) { Tile& tile = m_pZone->getTile(X, Y); const list<Object*>& oList = tile.getObjectList(); for (list<Object*>::const_iterator itr = oList.begin() ; itr != oList.end() ; itr++ ) { Object* pTargetObject = (*itr); if (pTargetObject != NULL && pTargetObject->getObjectClass() == Object::OBJECT_CLASS_CREATURE ) { Creature* pCreature = dynamic_cast<Creature*>(pTargetObject); Assert(pCreature != NULL); affect(pCreature); } } } } setNextTime(m_Turn); __END_CATCH }
//---------------------------------------------------------------------- // constructor //---------------------------------------------------------------------- EffectContinualGroundAttack::EffectContinualGroundAttack (Zone* pZone , EffectClass attackEffect, Turn_t delay) throw(Error) { __BEGIN_TRY Assert(pZone!=NULL); m_pZone = pZone; m_AttackEffect = attackEffect; m_Delay = delay; setNextTime(10); // 1초 후 시작 setDeadline(delay); m_MinNumber = 1; m_MaxNumber = 1; // 서버 전용 Effect이다. by sigi. 2002.11.14 m_bBroadcastingEffect = false; __END_CATCH }
void EffectSpiritGuard::affect(Creature* pCastCreature) throw(Error) { __BEGIN_TRY Assert(pCastCreature != NULL); if (!pCastCreature->isSlayer() ) return; Player* pPlayer = dynamic_cast<Player*>(pCastCreature->getPlayer()); Assert(pPlayer != NULL); Slayer* pSlayer = dynamic_cast<Slayer*>(pCastCreature); Assert(pSlayer != NULL); SkillInfo* pSkillInfo = g_pSkillInfoManager->getSkillInfo(SKILL_SPIRIT_GUARD); if (pSkillInfo == NULL ) { return; } GCModifyInformation gcAttackerMI; Zone* pZone = pCastCreature->getZone(); Assert(pZone != NULL); VSRect rect(0, 0, pZone->getWidth()-1, pZone->getHeight()-1); ZoneCoord_t Cx = pCastCreature->getX(); ZoneCoord_t Cy = pCastCreature->getY(); bool isHit = false; Level_t maxEnemyLevel = 0; uint EnemyNum = 0; for (int x=-1; x<=1; x++ ) { for (int y=-1; y<=1; y++ ) { if (x == 0 && y == 0 ) continue; int X = Cx + x; int Y = Cy + y; if (!rect.ptInRect(X, Y ) ) continue; // 타일안에 존재하는 오브젝트를 가져온다. Tile& tile = pZone->getTile(X, Y); if(tile.hasCreature(Creature::MOVE_MODE_WALKING) ) { Creature* pCreature = tile.getCreature(Creature::MOVE_MODE_WALKING); Assert(pCreature != NULL); // 자신은 맞지 않는다. 무적도 안 맞는다. 슬레이어도 안 맞느다. // 안전지대 체크 // 2003.1.10 by bezz, Sequoia if (pCreature == m_pTarget || !canAttack(pCastCreature, pCreature ) || pCreature->isFlag(Effect::EFFECT_CLASS_COMA ) || pCreature->isSlayer() || pCreature->isNPC() || !checkZoneLevelToHitTarget(pCreature) ) { continue; } isHit = true; if (maxEnemyLevel < pCreature->getLevel() ) maxEnemyLevel = pCreature->getLevel(); EnemyNum++; if (pCreature->isVampire() || pCreature->isOusters() ) { // Vampire* pVampire = dynamic_cast<Vampire*>(pCreature); GCModifyInformation gcMI; ::setDamage(pCreature, m_Damage, pCastCreature, SKILL_SPIRIT_GUARD, &gcMI, &gcAttackerMI); pCreature->getPlayer()->sendPacket(&gcMI); // 맞는 동작을 보여준다. GCSkillToObjectOK2 gcSkillToObjectOK2; gcSkillToObjectOK2.setObjectID(1); // 의미 없다. gcSkillToObjectOK2.setSkillType(SKILL_ATTACK_MELEE); gcSkillToObjectOK2.setDuration(0); pCreature->getPlayer()->sendPacket(&gcSkillToObjectOK2); } else if (pCreature->isMonster() ) { Monster* pMonster = dynamic_cast<Monster*>(pCreature); ::setDamage(pMonster, m_Damage, pCastCreature, SKILL_SPIRIT_GUARD, NULL, &gcAttackerMI); pMonster->addEnemy(pCastCreature); } else Assert(false); GCSkillToObjectOK4 gcSkillToObjectOK4; gcSkillToObjectOK4.setSkillType(SKILL_ATTACK_MELEE); gcSkillToObjectOK4.setTargetObjectID(pCreature->getObjectID()); gcSkillToObjectOK4.setDuration(0); pZone->broadcastPacket(X, Y, &gcSkillToObjectOK4, pCreature); } } } if (isHit ) { SkillDomainType_t DomainType = pSkillInfo->getDomainType(); SkillSlot* pSkillSlot = pSlayer->getSkill(SKILL_SPIRIT_GUARD); if (pSkillSlot != NULL ) { increaseDomainExp(pSlayer, DomainType, pSkillInfo->getPoint(), gcAttackerMI, maxEnemyLevel, EnemyNum); increaseSkillExp(pSlayer, DomainType, pSkillSlot, pSkillInfo, gcAttackerMI); } } setNextTime(m_Delay); __END_CATCH }
void EffectGreenStalker::affect(Creature* pCreature) throw(Error) { __BEGIN_TRY //cout << "EffectGreenStalker " << "affect BEGIN" << endl; Assert(pCreature != NULL); Zone* pZone = pCreature->getZone(); Assert(pZone != NULL); // 기술 사용자를 가져온다. // !! 이미 존을 나갔을 수 있으므로 NULL 이 될 수 있다. // by bezz. 2003.1.4 Creature* pCastCreature = pZone->getCreature(m_UserObjectID); if (pCastCreature == NULL ) { setNextTime(m_Tick); return; } int PoisonDamage = computeMagicDamage(pCreature, m_Damage, SKILL_GREEN_STALKER, m_bVampire, pCastCreature); // 무적상태 체크. by sigi. 2002.9.5 if (canAttack(pCastCreature, pCreature ) && !pCreature->isFlag(Effect::EFFECT_CLASS_COMA) ) { // 슬레이어일 경우에만 독 데미지가 존재한다. if (pCreature->isSlayer()) { Slayer* pSlayer = dynamic_cast<Slayer*>(pCreature); Assert(pSlayer != NULL); GCModifyInformation gcMI; ::setDamage(pSlayer, PoisonDamage, pCastCreature, SKILL_GREEN_STALKER, &gcMI); Player* pPlayer = pCreature->getPlayer(); Assert(pPlayer != NULL); pPlayer->sendPacket(&gcMI); } else if (pCreature->isVampire()) { Vampire* pVampire = dynamic_cast<Vampire*>(pCreature); Assert(pVampire != NULL); GCModifyInformation gcMI; ::setDamage(pVampire, PoisonDamage, pCastCreature, SKILL_GREEN_STALKER, &gcMI); Player* pPlayer = pCreature->getPlayer(); Assert(pPlayer != NULL); pPlayer->sendPacket(&gcMI); } else if (pCreature->isOusters()) { Ousters* pOusters = dynamic_cast<Ousters*>(pCreature); Assert(pOusters != NULL); GCModifyInformation gcMI; ::setDamage(pOusters, PoisonDamage, pCastCreature, SKILL_GREEN_STALKER, &gcMI); Player* pPlayer = pCreature->getPlayer(); Assert(pPlayer != NULL); pPlayer->sendPacket(&gcMI); } else if (pCreature->isMonster()) { Monster* pMonster = dynamic_cast<Monster*>(pCreature); Assert(pMonster != NULL); ::setDamage(pMonster, PoisonDamage, pCastCreature, SKILL_GREEN_STALKER); } // m_CasterName이 pCreature를 죽인 경우의 KillCount 처리 // by sigi. 2002.9.9 /* if (pCreature->isDead()) { Creature* pAttacker = pZone->getCreature(m_UserObjectID); if (pAttacker!=NULL) { affectKillCount(pAttacker, pCreature); } }*/ } setNextTime(m_Tick); //cout << "EffectGreenStalker " << "affect END" << endl; __END_CATCH }
void EffectPoison::affect(Creature* pCreature) throw(Error) { __BEGIN_TRY //cout << "EffectPoison " << "begin" << endl; Assert(pCreature != NULL); Zone* pZone = pCreature->getZone(); Assert(pZone != NULL); // 스킬 사용자를 가져온다. // !! 이미 존을 나갔을 수 있으므로 NULL이 될 수 있다. // by bezz. 2003.1.4 Creature* pCastCreature = pZone->getCreature(m_UserObjectID); // EffectPoison이 크리쳐에게 걸리게 되는 경우에는 현재로서는 // GreenPoison에 의해 타일 위에 생긴 // EffectGreenPoison 위를 플레이어가 지나갈 때 뿐이다. // EffectGreenPoison 내부에서 저항을 고려해서 데미지를 세팅한 다음 // EffectPoison을 붙이므로, 내부에서 한번 더 계산하면 안된다. //Damage_t PoisonDamage = computeMagicDamage(pCreature, m_Point, MAGIC_DOMAIN_POISON, m_Level); Damage_t PoisonDamage = m_Point; if (!(pZone->getZoneLevel() & COMPLETE_SAFE_ZONE) // 무적상태 체크. by sigi. 2002.9.5 && canAttack(pCastCreature, pCreature ) ) { if (pCreature->isSlayer()) { Slayer* pSlayer = dynamic_cast<Slayer*>(pCreature); GCModifyInformation gcMI; ::setDamage(pSlayer, PoisonDamage, pCastCreature, SKILL_GREEN_POISON, &gcMI); pSlayer->getPlayer()->sendPacket(&gcMI); } else if (pCreature->isVampire()) { Vampire* pVampire = dynamic_cast<Vampire*>(pCreature); GCModifyInformation gcMI; ::setDamage(pVampire, PoisonDamage, pCastCreature, SKILL_GREEN_POISON, &gcMI); pVampire->getPlayer()->sendPacket(&gcMI); } else if (pCreature->isOusters()) { Ousters* pOusters = dynamic_cast<Ousters*>(pCreature); GCModifyInformation gcMI; ::setDamage(pOusters, PoisonDamage, pCastCreature, SKILL_GREEN_POISON, &gcMI); pOusters->getPlayer()->sendPacket(&gcMI); } else if (pCreature->isMonster()) { Monster* pMonster = dynamic_cast<Monster*>(pCreature); ::setDamage(pMonster, PoisonDamage, pCastCreature, SKILL_GREEN_POISON); } // m_CasterName이 pCreature를 죽인 경우의 KillCount 처리 // by sigi. 2002.9.9 /* if (pCreature->isDead()) { Creature* pAttacker = pZone->getCreature(m_UserObjectID); if (pAttacker!=NULL) { affectKillCount(pAttacker, pCreature); } }*/ } setNextTime(m_Tick); //cout << "EffectPoison " << "end" << endl; __END_CATCH }
void EffectCureCriticalWounds::affect(Creature* pCreature) throw(Error) { __BEGIN_TRY Zone* pZone = pCreature->getZone(); Assert(pZone != NULL); GCSkillToSelfOK1 _GCSkillToSelfOK1; GCSkillToSelfOK2 _GCSkillToSelfOK2; int X = pCreature->getX(); int Y = pCreature->getY(); Exp_t ExpUp = 0; bool bCured = false; for(int oY = -2; oY <= 2; oY++) for(int oX = -2; oX <= 2; oX++) { int tileX = X+oX; int tileY = Y+oY; if (isValidZoneCoord(pZone, tileX, tileY)) { Tile& tile = pZone->getTile(tileX, tileY); if (tile.hasCreature(Creature::MOVE_MODE_WALKING ) ) { const list<Object*>& oList = tile.getObjectList(); for(list<Object*>::const_iterator itr = oList.begin(); itr != oList.end(); itr++) { Object* pTarget = *itr; Creature* pTargetCreature = NULL; if (pTarget->getObjectClass() == Object::OBJECT_CLASS_CREATURE && (pTargetCreature = dynamic_cast<Creature*>(pTarget))->isSlayer()) { Assert(pTargetCreature != NULL); HP_t RemainHP = 0; if (pTargetCreature->isSlayer() && !pTargetCreature->isFlag(Effect::EFFECT_CLASS_COMA) ) { Slayer* pSlayer = dynamic_cast<Slayer*>(pTargetCreature); HP_t CurrentHP = pSlayer->getHP(ATTR_CURRENT); HP_t MaxHP = pSlayer->getHP(ATTR_MAX); if (pTargetCreature->isFlag(Effect::EFFECT_CLASS_BLOOD_DRAIN)) { ExpUp++; Effect* pEffect = pSlayer->findEffect(Effect::EFFECT_CLASS_BLOOD_DRAIN); EffectBloodDrain * pEffectBloodDrain = dynamic_cast<EffectBloodDrain*>(pEffect); Assert(pEffectBloodDrain != NULL); if (pEffectBloodDrain->getLevel() < CriticalBloodDrainLevel ) { // 흡혈 아르바이트를 방지하기 위한 후유증 이펙트를 붙여준다. if (pSlayer->isFlag(Effect::EFFECT_CLASS_AFTERMATH)) { Effect* pEffect = pSlayer->findEffect(Effect::EFFECT_CLASS_AFTERMATH); EffectAftermath* pEffectAftermath = dynamic_cast<EffectAftermath*>(pEffect); pEffectAftermath->setDeadline(5*600); // 5분 동안 지속된다. } else { EffectAftermath* pEffectAftermath = new EffectAftermath(pSlayer); pEffectAftermath->setDeadline(5*600); // 5분 동안 지속된다. pSlayer->addEffect(pEffectAftermath); pSlayer->setFlag(Effect::EFFECT_CLASS_AFTERMATH); pEffectAftermath->create(pSlayer->getName()); } pEffectBloodDrain->destroy(pSlayer->getName()); pSlayer->deleteEffect(Effect::EFFECT_CLASS_BLOOD_DRAIN); bCured = true; SLAYER_RECORD prev; pSlayer->getSlayerRecord(prev); pSlayer->initAllStat(); pSlayer->sendRealWearingInfo(); pSlayer->sendModifyInfo(prev); GCRemoveEffect gcRemoveEffect; gcRemoveEffect.setObjectID(pSlayer->getObjectID()); gcRemoveEffect.addEffectList((EffectID_t)Effect::EFFECT_CLASS_BLOOD_DRAIN); pZone->broadcastPacket(pSlayer->getX(), pSlayer->getY(), &gcRemoveEffect); } } if(CurrentHP < MaxHP ) { ExpUp++; bCured = true; RemainHP = min(CurrentHP + m_Point,(int)MaxHP); pSlayer->setHP(RemainHP, ATTR_CURRENT); GCModifyInformation gcMI; gcMI.addShortData(MODIFY_CURRENT_HP, RemainHP); pSlayer->getPlayer()->sendPacket(&gcMI); _GCSkillToSelfOK1.setSkillType(SKILL_CURE_EFFECT); _GCSkillToSelfOK1.setDuration(0); pSlayer->getPlayer()->sendPacket(&_GCSkillToSelfOK1); _GCSkillToSelfOK2.setObjectID(pSlayer->getObjectID()); _GCSkillToSelfOK2.setSkillType(SKILL_CURE_EFFECT); _GCSkillToSelfOK2.setDuration(0); pZone->broadcastPacket(pTargetCreature->getX(), pTargetCreature->getY(), &_GCSkillToSelfOK2, pTargetCreature); Zone* pZone = pTargetCreature->getZone(); GCStatusCurrentHP gcStatusCurrentHP; gcStatusCurrentHP.setObjectID(pTargetCreature->getObjectID()); gcStatusCurrentHP.setCurrentHP(RemainHP); pZone->broadcastPacket(pTargetCreature->getX(), pTargetCreature->getY(), &gcStatusCurrentHP); } } } } } } } SkillInfo * pSkillInfo = g_pSkillInfoManager->getSkillInfo(SKILL_CURE_CRITICAL_WOUNDS); if(pSkillInfo != NULL && bCured ) { SkillSlot * pSkillSlot = ((Slayer*)pCreature)->hasSkill(SKILL_CURE_CRITICAL_WOUNDS); if(pSkillSlot != NULL ) { Slayer * pCastSlayer = dynamic_cast<Slayer*>(pCreature); GCModifyInformation gcMI; SkillDomainType_t DomainType = pSkillInfo->getDomainType(); // 경험치를 올려준다. shareAttrExp(pCastSlayer, ExpUp, 1 , 1 , 8, gcMI); increaseDomainExp(pCastSlayer, DomainType, ExpUp, gcMI); increaseSkillExp(pCastSlayer, DomainType, pSkillSlot, pSkillInfo, gcMI); pCastSlayer->getPlayer()->sendPacket(&gcMI); } } //cout << "EffectCureCriticalWounds " << "affect BEGIN" << endl; setNextTime(m_Delay); //cout << "EffectCureCriticalWounds " << "affect END" << endl; __END_CATCH }
void EffectContinualGroundAttack::affect() throw(Error) { __BEGIN_TRY Assert(m_pZone!=NULL); int creatureNum = m_pZone->getPCManager()->getSize() + m_pZone->getMonsterManager()->getSize(); // 부하를 조금이라도 줄이기 위해서.. // 존에 공격받을 캐릭터가 있어야지 effect를 붙이지.. if (creatureNum > 0) { // zone의 특정 위치에 effect를 출력하고 damage를 준다. int range = min(100, (m_MaxNumber-m_MinNumber)); // 동시에 1~100사이 int number = (range>0? m_MinNumber + rand()%range : m_MinNumber); VSRect rect(0, 0, m_pZone->getWidth()-1, m_pZone->getHeight()-1); // m_MinNumber ~ m_MaxNumber 개의 공격 for (int i=0; i<number; i++) { const BPOINT& pt = m_pZone->getRandomEmptyTilePosition(); if (!rect.ptInRect(pt.x, pt.y)) continue; // 중심 타일 체크 Tile& tile = m_pZone->getTile(pt.x, pt.y); int X = pt.x; int Y = pt.y; if (!tile.canAddEffect()) continue; int DamagePercent = 100; // 이펙트 오브젝트를 생성한다. Effect* pAttackEffect = NULL; switch (m_AttackEffect) { case EFFECT_CLASS_GROUND_ATTACK : { // 같은 이펙트가 이미 존재한다면 더 쎈 damage로 설정한다. Effect* pOldEffect = tile.getEffect(Effect::EFFECT_CLASS_GROUND_ATTACK); if (pOldEffect != NULL) { EffectGroundAttack* pGAEffect = dynamic_cast<EffectGroundAttack*>(pOldEffect); pGAEffect->setDamagePercent(max(DamagePercent, pGAEffect->getDamagePercent())); continue; } EffectGroundAttack* pEffect = new EffectGroundAttack(m_pZone, X, Y); pEffect->setDeadline(22); // 2초+알파 pEffect->setDamagePercent(DamagePercent); pAttackEffect = pEffect; } break; case EFFECT_CLASS_METEOR_STRIKE : { // 같은 이펙트가 있다면 삭제한다. Effect* pOldEffect = tile.getEffect(Effect::EFFECT_CLASS_METEOR_STRIKE); if (pOldEffect != NULL ) { ObjectID_t effectID = pOldEffect->getObjectID(); m_pZone->deleteEffect(effectID); } EffectMeteorStrike* pEffect = new EffectMeteorStrike(m_pZone, X, Y); pEffect->setDeadline(10); // 1초 // 400 ~ 600 100% // 200 ~ 300 50% // 100 ~ 150 25% pEffect->setDamage(400+rand()%200); pAttackEffect = pEffect; } break; default : break; } if (pAttackEffect!=NULL) { // 타일에 붙은 이펙트는 OID를 받아야 한다. ObjectRegistry & objectregister = m_pZone->getObjectRegistry(); objectregister.registerObject(pAttackEffect); // 존 및 타일에다가 이펙트를 추가한다. m_pZone->addEffect(pAttackEffect); tile.addEffect(pAttackEffect); // 가운데꺼만 이펙트를 보여준다. GCAddEffectToTile gcAddEffectToTile; gcAddEffectToTile.setEffectID(pAttackEffect->getEffectClass()); gcAddEffectToTile.setObjectID(pAttackEffect->getObjectID()); gcAddEffectToTile.setXY(X, Y); gcAddEffectToTile.setDuration(20); // 2초 m_pZone->broadcastPacket(X, Y, &gcAddEffectToTile); } } } setNextTime(m_Delay); __END_CATCH }
void EffectRelicPosition::affect(Item* pItem) throw(Error) { __BEGIN_TRY // 존 정보를 얻는다. ZoneInfo* pZoneInfo = g_pZoneInfoManager->getZoneInfo(m_ZoneID); Assert(pZoneInfo != NULL); if (pItem->getItemClass() == Item::ITEM_CLASS_RELIC) { // 성물의 정보를 얻는다. ItemType_t relicIndex = pItem->getItemType(); const RelicInfo* pRelicInfo = dynamic_cast<RelicInfo*>(g_pRelicInfoManager->getItemInfo(relicIndex)); Assert(pRelicInfo != NULL); // StringStream msg; /* // 위치를 알린다. msg << "성물(" << pRelicInfo->getName() << ")이 " << pZoneInfo->getFullName() << "(" << (int)m_X << ", " << (int)m_Y << ")에 떨어져 있습니다."; */ char msg[100]; sprintf(msg, g_pStringPool->c_str(STRID_RELIC_IN_ZONE ), pRelicInfo->getName().c_str(), pZoneInfo->getFullName().c_str(), (int)m_X, (int)m_Y ); GCSystemMessage gcSystemMessage; gcSystemMessage.setType(SYSTEM_MESSAGE_COMBAT); gcSystemMessage.setMessage(msg); g_pHolyLandManager->broadcast(&gcSystemMessage); setNextTime(m_Tick); } else if (pItem->getItemClass() == Item::ITEM_CLASS_BLOOD_BIBLE) { ShrineSet* pShrineSet = g_pShrineInfoManager->getShrineSet(m_Part); Assert(pShrineSet!=NULL); GCBloodBibleStatus* pGCBBS = new GCBloodBibleStatus; pGCBBS->setItemType(m_Part); pGCBBS->setZoneID(m_ZoneID); pGCBBS->setStorage(STORAGE_ZONE); //pGCBBS->setRace(pShrineSet->getOwnerRace()); pGCBBS->setShrineRace(pShrineSet->getOwnerRace()); pGCBBS->setX(m_X); pGCBBS->setY(m_Y); // g_pHolyLandManager->broadcast(pGCBBS); g_pZoneGroupManager->broadcast(pGCBBS); g_pShrineInfoManager->registerBloodBibleStatus(m_Part, pGCBBS); /* msg << "피의 성서 조각이 " << pZoneInfo->getFullName() << "(" << (int)m_X << ", " << (int)m_Y << ")에 떨어져 있습니다."; g_pZoneGroupManager->broadcast(&gcSystemMessage); */ setNextTime(999999); } else if (pItem->getItemClass() == Item::ITEM_CLASS_CASTLE_SYMBOL) { // StringStream msg; // msg << "성의 상징이 " // << pZoneInfo->getFullName() << "(" << (int)m_X << ", " << (int)m_Y << ")에 떨어져 있습니다."; char msg[200]; sprintf(msg, g_pStringPool->c_str(STRID_BROADCAST_CASTLE_SYMBOL_POSITION_3 ), pZoneInfo->getFullName().c_str(), (int)m_X, (int)m_Y); GCSystemMessage gcSystemMessage; gcSystemMessage.setType(SYSTEM_MESSAGE_HOLY_LAND); gcSystemMessage.setMessage(msg); g_pCastleInfoManager->broadcastShrinePacket(m_Part, &gcSystemMessage); setNextTime(m_Tick); // g_pZoneGroupManager->broadcast(&gcSystemMessage); } else { return; } __END_CATCH }
void EffectHasVampireRelic::affect(Creature* pCreature) throw(Error) { __BEGIN_TRY //Timeval nextTime = getNextTime(); //Timeval deadLine = getDeadline(); //Turn_t RemainTime = deadLine.tv_sec - nextTime.tv_sec; /* StringStream msg; if (pCreature->isSlayer()) { Slayer* pSlayer = dynamic_cast<Slayer*>(pCreature); msg << pSlayer->getName(); } else { Vampire* pVampire = dynamic_cast<Vampire*>(pCreature); msg << pVampire->getName(); } msg << " 님이 뱀파이어 성물을 가졌습니다."; GCSystemMessage gcSystemMessage; gcSystemMessage.setMessage(msg.toString()); g_pZoneGroupManager->broadcast(&gcSystemMessage); */ // 존 정보를 얻는다. Zone* pZone = pCreature->getZone(); Assert(pZone!=NULL); ZoneInfo* pZoneInfo = g_pZoneInfoManager->getZoneInfo(pZone->getZoneID()); Assert(pZoneInfo != NULL); // 위치를 알린다. char msg[100]; const char* race; if (pCreature->isSlayer() ) { race = g_pStringPool->c_str(STRID_SLAYER); } else if (pCreature->isVampire() ) { race = g_pStringPool->c_str(STRID_VAMPIRE); } else if (pCreature->isOusters() ) { race = g_pStringPool->c_str(STRID_OUSTERS); } sprintf(msg, g_pStringPool->c_str(STRID_HAVING_VAMPIRE_RELIC ), pCreature->getName().c_str(), race, // (pCreature->isSlayer() ? g_pStringPool->c_str(STRID_SLAYER ) : g_pStringPool->c_str(STRID_VAMPIRE ) ), (int)pCreature->getX(), (int)pCreature->getY() ); /* // 위치를 알린다. StringStream msg; msg << pCreature->getName() << " 님(" << (pCreature->isSlayer() ? "슬레이어" : "뱀파이어" ) << ")이 " << pZoneInfo->getFullName() << "(" << (int)pCreature->getX() << ", " << (int)pCreature->getY() << ")에서 뱀파이어 성물을 가지고 있습니다."; */ GCSystemMessage gcSystemMessage; gcSystemMessage.setMessage(msg); g_pZoneGroupManager->broadcast(&gcSystemMessage); setNextTime(m_Tick); __END_CATCH }
void EffectStormPoison::affect(Creature* pCreature) throw(Error) { __BEGIN_TRY //cout << "EffectStormPoison " << "begin" << endl; Assert(pCreature != NULL); Zone* pZone = pCreature->getZone(); Assert(pZone != NULL); // 사용자를 가져온다. // !! 이미 존을 나갔을 수 있으므로 NULL이 될 수 있다. // by bezz. 2003.3.13 Creature* pCastCreature = pZone->getCreature(m_UserObjectID); // 캐스터가 없으면 무시한다. if (pCastCreature == NULL ) return; // EffectStormPoison은 AcidStorm, PoisonStorm, BloodyStorm위를 지나갈때 붙는다. // 이는 3번의 연속 데미지를 주고 사라진다. Damage_t StormDamage = m_Point; GCModifyInformation GCAttackerMI; if (!(pZone->getZoneLevel() & COMPLETE_SAFE_ZONE) // 무적상태 체크. by sigi. 2002.9.5 && canAttack(pCastCreature, pCreature ) ) { if (pCreature->isSlayer()) { Slayer* pSlayer = dynamic_cast<Slayer*>(pCreature); GCModifyInformation gcMI; setDamage(pSlayer, StormDamage, pCastCreature, SKILL_POISON_STORM, &gcMI, &GCAttackerMI); pSlayer->getPlayer()->sendPacket(&gcMI); } else if (pCreature->isVampire()) { Vampire* pVampire = dynamic_cast<Vampire*>(pCreature); GCModifyInformation gcMI; setDamage(pVampire, StormDamage, pCastCreature, SKILL_POISON_STORM, &gcMI, &GCAttackerMI); pVampire->getPlayer()->sendPacket(&gcMI); } else if (pCreature->isOusters()) { Ousters* pOusters = dynamic_cast<Ousters*>(pCreature); GCModifyInformation gcMI; setDamage(pOusters, StormDamage, pCastCreature, SKILL_POISON_STORM, &gcMI, &GCAttackerMI); pOusters->getPlayer()->sendPacket(&gcMI); } else if (pCreature->isMonster()) { Monster* pMonster = dynamic_cast<Monster*>(pCreature); setDamage(pMonster, StormDamage, pCastCreature, SKILL_POISON_STORM, NULL, &GCAttackerMI); } if (pCastCreature->isVampire() && pCreature->isDead() ) { Vampire* pVampire = dynamic_cast<Vampire*>(pCastCreature); int exp = computeCreatureExp(pCreature, KILL_EXP); shareVampExp(pVampire, exp, GCAttackerMI); pVampire->getPlayer()->sendPacket(&GCAttackerMI); } // m_CasterName이 pCreature를 죽인 경우의 KillCount 처리 // by sigi. 2002.9.9 // set damage 를 불러서 처리한다. 주석 처리 // by bezz. 2002.12.31 /* if (pCreature->isDead()) { Creature* pAttacker = pZone->getCreature(m_UserObjectID); if (pAttacker!=NULL) { affectKillCount(pAttacker, pCreature); } }*/ } setNextTime(m_Tick); //cout << "EffectStormPoison " << "end" << endl; __END_CATCH }
void EffectHasBloodBible::affect(Creature* pCreature) throw(Error) { __BEGIN_TRY //Timeval nextTime = getNextTime(); //Timeval deadLine = getDeadline(); //Turn_t RemainTime = deadLine.tv_sec - nextTime.tv_sec; /* StringStream msg; if (pCreature->isSlayer()) { Slayer* pSlayer = dynamic_cast<Slayer*>(pCreature); msg << pSlayer->getName(); } else { Vampire* pVampire = dynamic_cast<Vampire*>(pCreature); msg << pVampire->getName(); } msg << " 님이 슬레이어 성물을 가졌습니다."; GCSystemMessage gcSystemMessage; gcSystemMessage.setMessage(msg.toString()); g_pZoneGroupManager->broadcast(&gcSystemMessage); */ // 존 정보를 얻는다. Zone* pZone = pCreature->getZone(); Assert(pZone!=NULL); /* ZoneInfo* pZoneInfo = g_pZoneInfoManager->getZoneInfo(pZone->getZoneID()); Assert(pZoneInfo != NULL); // 위치를 알린다. StringStream msg; msg << pCreature->getName() << " 님(" << (pCreature->isSlayer() ? "슬레이어" : "뱀파이어" ) << ")이 " << pZoneInfo->getFullName() << "(" << (int)pCreature->getX() << ", " << (int)pCreature->getY() << ")에서 피의 성서 조각(" << m_PartName << ")을 가지고 있습니다."; GCSystemMessage gcSystemMessage; gcSystemMessage.setMessage(msg.toString()); g_pZoneGroupManager->broadcast(&gcSystemMessage); */ ShrineSet* pShrineSet = g_pShrineInfoManager->getShrineSet(m_Part); Assert(pShrineSet!=NULL); Race_t ShrineRace = pShrineSet->getOwnerRace(); GCBloodBibleStatus* pGCBBS = new GCBloodBibleStatus; pGCBBS->setItemType(m_Part); pGCBBS->setZoneID(pZone->getZoneID()); pGCBBS->setStorage(STORAGE_INVENTORY); pGCBBS->setOwnerName(pCreature->getName()); pGCBBS->setRace(pCreature->getRace()); pGCBBS->setShrineRace(ShrineRace); pGCBBS->setX(pCreature->getX()); pGCBBS->setY(pCreature->getY()); // g_pHolyLandManager->broadcast(pGCBBS); g_pZoneGroupManager->broadcast(pGCBBS); g_pShrineInfoManager->registerBloodBibleStatus(m_Part, pGCBBS); setNextTime(m_Tick); __END_CATCH }
void EffectVigorDropToCreature::affect(Creature* pCreature) throw(Error) { __BEGIN_TRY //cout << "EffectVigorDropToCreature " << "begin" << endl; Assert(pCreature != NULL); Zone* pZone = pCreature->getZone(); Assert(pZone != NULL); // 스킬 사용자를 가져온다. // !! 이미 존을 나갔을 수 있으므로 NULL이 될 수 있다. // by bezz. 2003.1.4 Creature* pCastCreature = pZone->getCreature(m_UserObjectID); // EffectVigorDropToCreature은 AcidStorm, PoisonStorm, BloodyStorm위를 지나갈때 붙는다. // 이는 3번의 연속 데미지를 주고 사라진다. Damage_t DropDamage = m_Point; if (!(pZone->getZoneLevel() & COMPLETE_SAFE_ZONE) // 무적상태 체크. by sigi. 2002.9.5 && canAttack(pCastCreature, pCreature ) && !pCreature->isFlag(Effect::EFFECT_CLASS_COMA) ) { if (pCreature->isSlayer()) { Slayer* pSlayer = dynamic_cast<Slayer*>(pCreature); GCModifyInformation gcMI; setDamage(pSlayer, DropDamage, pCastCreature, SKILL_VIGOR_DROP, &gcMI); pSlayer->getPlayer()->sendPacket(&gcMI); } else if (pCreature->isVampire()) { Vampire* pVampire = dynamic_cast<Vampire*>(pCreature); GCModifyInformation gcMI; setDamage(pVampire, DropDamage, pCastCreature, SKILL_VIGOR_DROP, &gcMI); pVampire->getPlayer()->sendPacket(&gcMI); } else if (pCreature->isOusters()) { Ousters* pOusters = dynamic_cast<Ousters*>(pCreature); GCModifyInformation gcMI; setDamage(pOusters, DropDamage, pCastCreature, SKILL_VIGOR_DROP, &gcMI); pOusters->getPlayer()->sendPacket(&gcMI); } else if (pCreature->isMonster()) { Monster* pMonster = dynamic_cast<Monster*>(pCreature); setDamage(pMonster, DropDamage, pCastCreature, SKILL_VIGOR_DROP); } // m_CasterName이 pCreature를 죽인 경우의 KillCount 처리 // by sigi. 2002.9.9 // setDamage 를 불러서 처리한다. 주석처리 // by bezz. 2002.12.31 /* if (pCreature->isDead()) { Creature* pAttacker = pZone->getCreature(m_CasterName); if (pAttacker!=NULL) { affectKillCount(pAttacker, pCreature); } }*/ } setNextTime(m_Tick); //cout << "EffectVigorDropToCreature " << "end" << endl; __END_CATCH }