bool UnitClass::canAttackNow(Unit unit) { if(!unit || !exists() || !unit->exists()) return false; return canAttack(unit); }
void Anakin::attack(float xLoc, float yLoc){ if (!canAttack()) return; float x = this->getPosition().x; if (xLoc > centralPoint.x&&direction != 1){ direction = 1; } if (xLoc < centralPoint.x&&direction == 1){ direction = -1; } float newX = this->getPosition().x; if (yLoc > centralPoint.y){ if (direction==1) mAnimation->play("hit", false); else mAnimation->play("hitRevert", false); } else{ if (direction == 1) mAnimation->play("hit2", false); else mAnimation->play("hit2Revert", false); } float attackBoost = GameConfig::currentScore / 200; if (attackBoost > 1.5f) attackBoost = 1.5f; //attackBoost = 1.5f; mAnimation->setTimeSpeed(1.1 + attackBoost); }
//----------Collider abfragen---------// //PlayerCollider* Loewenzahn::getPlayerColliderComponent() //{ // return dynamic_cast<PlayerCollider*>(this->getComponent("playerCollider")); //} //----------GameLoop-----------// void Loewenzahn::update(float dt) { //this->getPlayerColliderComponent()->update(dt); //this->setAffectedByGravity(false); Moveable::update(dt); //this->CheckForCollisions(); if (this->m_isAlive) { if (canAttack()) { this->moodAttack(dt); } else { this->moodIdle(dt); } } else if (!(this->m_isAlive)) { this->moodDie(dt); } }
int TargetingAgent::getNoAttackers(BaseAgent* agent) { int cnt = 0; for(set<Unit*>::const_iterator i=Broodwar->enemy()->getUnits().begin(); i!=Broodwar->enemy()->getUnits().end(); i++) { if (canAttack((*i)->getType())) { int enemyMSD = 0; if (agent->getUnitType().isFlyer()) { enemyMSD = (*i)->getType().airWeapon().maxRange(); } else { enemyMSD = (*i)->getType().groundWeapon().maxRange(); } double d = agent->getUnit()->getPosition().getDistance((*i)->getPosition()); if (d <= enemyMSD) { cnt++; } } } return cnt; }
void Monster::attack(Ninja* p){ if (canAttack()){ this->multiplier = 0; p->changeHealth(-1 * this->damage); this->readyToAttack = false; } }
void Zombie::attack(Player* p){ if(canAttack()){ this->multiplier = 0; p->changeHealth(-1*this->damage); this->readyToAttack = false; } }
int UnitAgent::enemyAirAttackingUnitsWithinRange(TilePosition center, int maxRange) { if (maxRange < 0) { return 0; } int eCnt = 0; for(set<Unit*>::const_iterator i=Broodwar->enemy()->getUnits().begin();i!=Broodwar->enemy()->getUnits().end();i++) { //Enemy seen if ((*i)->exists()) { if ((*i)->getType().isFlyer() || (*i)->getType().isFlyingBuilding()) { if (canAttack((*i)->getType(), unit->getType())) { double dist = (*i)->getDistance(Position(center)); if (dist <= maxRange) { eCnt++; } } } } } return eCnt; }
void UnitBase::doAttackObject(const ObjectBase* pTargetObject, bool bForced) { if (pTargetObject == NULL) { return; } if(pTargetObject->getObjectID() == getObjectID() || (!canAttack() && getItemID() != Unit_Harvester)) { return; } if(attackMode == CAPTURE) { doSetAttackMode(GUARD); } setDestination(INVALID_POS,INVALID_POS); setTarget(pTargetObject); // hack to make it possible to attack own repair yard if(goingToRepairYard && target && (target.getObjPointer()->getItemID() == Structure_RepairYard)) { ((RepairYard*)target.getObjPointer())->unBook(); goingToRepairYard = false; } setForced(bForced); clearPath(); findTargetTimer = 0; }
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 Monster::readyAttack(double delta){ if (!canAttack()){ cooldown += (float)delta; if (cooldown >= 100000.0){ readyToAttack = true; cooldown = 0.0; } } }
//charging attack depending on a interval time, so wont attack every second void Zombie::chargeAttack(double delta){ if(!canAttack()){ attackTimer += (float) delta; //interval time 200000.0 if(attackTimer >= 200000.0){ readyToAttack = true; attackTimer = 0.0; } } }
void TurretClass::doSpecificStuff() { if (target && (target.getObjPointer() != NULL)) { if (!canAttack(target.getObjPointer()) || !targetInWeaponRange()) { setTarget(NULL); } else if (targetInWeaponRange()) { Coord closestPoint = target.getObjPointer()->getClosestPoint(location); double destAngle = dest_angle(location, closestPoint); int wantedAngle = lround(8.0/256.0*destAngle); if(wantedAngle == 8) { wantedAngle = 0; } if(angle != wantedAngle) { // turn double angleLeft = 0.0; double angleRight = 0.0; if(angle > wantedAngle) { angleRight = angle - wantedAngle; angleLeft = fabs(8-angle)+wantedAngle; } else if (angle < wantedAngle) { angleRight = abs(8-wantedAngle) + angle; angleLeft = wantedAngle - angle; } if(angleLeft <= angleRight) { turnLeft(); } else { turnRight(); } } if(drawnAngle == wantedAngle) { attack(); } } else { setTarget(NULL); } } else if ((attackMode != STOP) && (findTargetTimer == 0)) { setTarget(findTarget()); findTargetTimer = 100; } if (findTargetTimer > 0) findTargetTimer--; if (weaponTimer > 0) weaponTimer--; }
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 Animal::fight(AbstractBattleEntity* entity) { if (canAttack() == false) { return; } _state = AnimalState::Battle; _target = entity; _target->retain(); Vec2 originPoint = getPosition(); Vec2 targetPoint = ZMath::divideInternally(getPosition(), entity->getPosition(), 1, 2); auto size = _image->getContentSize() * getScale(); Vec2 effectPoint = ZMath::divideInternally(getPosition(), entity->getPosition(), 1, 1) + Vec2(0, size.height / 2); _timeline->play("default", false); _stopMoveAction(); _moveAction = runAction(RepeatForever::create(Sequence::create( MoveTo::create(0.1f, targetPoint), CallFunc::create([this, effectPoint]() { // sound effect if (isEnemy() || isOpponent()) { SoundManager::getInstance()->playFight2Sound(); } else { SoundManager::getInstance()->playFightSound(); } // particle effect auto effect = ParticleSystemQuad::create("effect/hit3.plist"); effect->setScale(getScale()); effect->setPosition(effectPoint); effect->setZOrder(100000); effect->setAutoRemoveOnFinish(true); auto parent = getParent(); if (parent) { parent->addChild(effect); } }), MoveTo::create(0.3f, originPoint), DelayTime::create(0.5f), NULL ))); _moveAction->retain(); if (startFightCallback) { startFightCallback(this, _target); } }
bool Monster::targetClosestEnemy() { auto& game = server.game(); auto position = getPosition(); SpectatorList spectators; game.getSpectators(spectators, position); if (spectators.empty()) { target(nullptr); return false; } auto closestDistance = std::numeric_limits<uint32_t>::max(); CreatureP closestSpectator; for (auto spectator : spectators) { if (!isEnemy(*spectator)) { continue; } if (!canAttack(*spectator)) { continue; } auto spectatorPosition = spectator->getPosition(); if (!game.isSightClear(position, spectatorPosition, true)) { continue; } auto distance = position.distanceTo(spectatorPosition); if (distance < closestDistance) { closestSpectator = spectator; if (distance == 1) { break; } closestDistance = distance; } } if (closestSpectator == nullptr) { target(nullptr); return false; } return target(closestSpectator); }
////////////////////////////////////////////////////////////////////////////// // 아우스터즈 오브젝트 핸들러 ////////////////////////////////////////////////////////////////////////////// void Prominence::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); // NPC는 공격할 수가 없다. if (pTargetCreature==NULL // NoSuch제거 때문에.. by sigi. 2002.5.2 || !canAttack(pOusters, pTargetCreature ) || 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 }
//----------GameLoop-----------// void SlimeHeap::update(float dt) { if (m_pPlayer == nullptr) { this->m_pPlayer = m_layer->getPlayer(); return; } //this->getPlayerColliderComponent()->update(dt); //this->setAffectedByGravity(false); Moveable::update(dt); //this->CheckForCollisions(); //if (m_pPlayer->getPlayerColliderComponent()->getBottomCollider().intersectsRect(this->getColliderComponent()->getCollisionRectangle()) // && ((m_pPlayer->getPositionY()) - (this->getPositionY())) >= 170) //{ // m_isAlive = false; //} if (this->getAffectedByGrafity() == false) { this->setAffectedByGravity(true); } if (this->m_isAlive) { if (canAttack()) { this->moodAttack(dt); } else { this->moodWalk(dt); } } else if (!(this->m_isAlive) && !m_isDead) { this->moodDie(dt); } else { removeFromParentAndCleanup(true); // gegner entfernen } }
void UnitBase::handleDamage(int damage, Uint32 damagerID, House* damagerOwner) { // shorten deviation time if(deviationTimer > 0) { deviationTimer = std::max(0,deviationTimer - MILLI2CYCLES(damage*20*1000)); } ObjectBase::handleDamage(damage, damagerID, damagerOwner); if(attackMode == HUNT && !forced) { ObjectBase* pDamager = currentGame->getObjectManager().getObject(damagerID); if(pDamager != NULL && canAttack(pDamager)) { if(!target || target.getObjPointer() == NULL || !isInWeaponRange(target.getObjPointer())) { // no target or target not on weapon range => switch target doAttackObject(pDamager, false); } } } }
bool Monster::canBeChallengedBy(const CreatureP& challenger) const { if (challenger == nullptr) { assert(challenger != nullptr); return false; } if (challenger == this) { return false; } if (hasController()) { return false; } if (!canAttack(*challenger)) { return false; } return true; }
bool Monster::targetRandomEnemy() { auto& game = server.game(); auto position = getPosition(); SpectatorList spectators; game.getSpectators(spectators, position); if (spectators.empty()) { target(nullptr); return false; } for (auto i = spectators.begin(); i != spectators.end(); ) { auto& spectator = *i; if (!isEnemy(*spectator)) { i = spectators.erase(i); continue; } if (!canAttack(*spectator)) { i = spectators.erase(i); continue; } if (!game.isSightClear(position, spectator->getPosition(), true)) { i = spectators.erase(i); continue; } ++i; } if (spectators.empty()) { target(nullptr); return false; } auto randomEnemy = *std::next(spectators.begin(), random_range<uint32_t>(0, spectators.size() - 1)); return target(randomEnemy); }
////////////////////////////////////////////////////////////////////////////// // 슬레이어 오브젝트 핸들러 ////////////////////////////////////////////////////////////////////////////// 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 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 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 Monster::updateTarget() { if (hasMaster()) { target(_master->getAttackedCreature()); } else { CreatureP attackedCreature = this->attackedCreature; if (attackedCreature == nullptr || !canAttack(*attackedCreature)) { retarget(); } else { // retarget if target is out of sight + we cannot walk there auto& game = server.game(); if (!game.isSightClear(getPosition(), attackedCreature->getPosition(), true)) { FindPathParams parameters; getPathSearchParams(attackedCreature.get(), parameters); DirectionRoute route; if (!server.game().getPathToEx(this, attackedCreature->getPosition(), route, parameters)) { retarget(); } } } } }
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 EffectPlasmaRocketLauncher::affect(Creature* pCreature) throw(Error) { __BEGIN_TRY __BEGIN_DEBUG Assert(pCreature != NULL); Zone* pZone = pCreature->getZone(); Assert(pZone != NULL); Creature* pAttacker = pZone->getCreature(m_UserObjectID); VSRect rect(0, 0, pZone->getWidth()-1, pZone->getHeight()-1); int cX = pCreature->getX(); int cY = pCreature->getY(); for(int x = -1; x <= 1; x++) { for(int y= -1; y <= 1; y++) { int X = cX + x; int Y = cY + y; if(!rect.ptInRect(X, Y)) continue; Tile& tile = pZone->getTile(X, Y); const list<Object*>& oList = tile.getObjectList(); list<Object*>::const_iterator itr = oList.begin(); for(; itr != oList.end(); itr++) { Assert(*itr != NULL); Object* pObject = *itr; Assert(pObject != NULL); if(pObject->getObjectClass() == Object::OBJECT_CLASS_CREATURE) { Creature* pCreature2 = dynamic_cast<Creature*>(pObject); Assert(pCreature2 != NULL); if (pCreature2 != pCreature && pCreature2->isSlayer() ) continue; if (!(pZone->getZoneLevel() & COMPLETE_SAFE_ZONE) && !pCreature2->isDead() && !pCreature2->isFlag(Effect::EFFECT_CLASS_COMA) // 무적상태 체크. by sigi. 2002.9.5 && canAttack(pAttacker, pCreature2 ) ) { GCModifyInformation gcMI, gcAttackerMI; setDamage(pCreature2, m_Point, pAttacker, SKILL_PLASMA_ROCKET_LAUNCHER, &gcMI, &gcAttackerMI); if (pCreature2->isPC() ) pCreature2->getPlayer()->sendPacket(&gcMI); if (pAttacker!=NULL) { computeAlignmentChange(pCreature2, m_Point, pAttacker, &gcMI, &gcAttackerMI); if (pAttacker->isPC() ) { if (pAttacker->isSlayer() && !pCreature2->isSlayer() ) { Slayer* pSlayer = dynamic_cast<Slayer*>(pAttacker); if (pSlayer != NULL ) { GCModifyInformation gcMI; shareAttrExp(pSlayer, m_Point, 1, 8, 1, gcAttackerMI); } } if (pAttacker->isPC() ) pAttacker->getPlayer()->sendPacket(&gcAttackerMI); } } } } } } } setDeadline(0); __END_DEBUG __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 BloodDrain::execute(Vampire* pVampire, ObjectID_t TargetObjectID) throw(Error) { __BEGIN_TRY //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " Begin(vampire)" << endl; Assert(pVampire != 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 // 무적상태 체크. by sigi.2002.9.5 // 죽은 애는 피 빨 수 없다. by Sequoia.2003. 3. 20 if (pTargetCreature==NULL // NoSuch 제거. by sigi. 2002.5.2 || pTargetCreature->isNPC() || pTargetCreature->isFlag(Effect::EFFECT_CLASS_IMMUNE_TO_BLOOD_DRAIN) || !canAttack(pVampire, pTargetCreature ) || pTargetCreature->isFlag(Effect::EFFECT_CLASS_COMA) || pTargetCreature->isDead() ) { executeSkillFailException(pVampire, getSkillType()); //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End(vampire)" << endl; return; } GCBloodDrainOK1 _GCBloodDrainOK1; GCBloodDrainOK2 _GCBloodDrainOK2; GCBloodDrainOK3 _GCBloodDrainOK3; Timeval CurrentTime; getCurrentTime(CurrentTime); bool bHitRoll = HitRoll::isSuccessBloodDrain(pVampire, pTargetCreature); bool bCanHit = canHit(pVampire, pTargetCreature, SKILL_BLOOD_DRAIN); bool bTimeCheck = CurrentTime.tv_sec > 1 ? true : false; bool bRangeCheck = verifyDistance(pVampire, pTargetCreature, 2); bool bPK = verifyPK(pVampire, pTargetCreature); if (bHitRoll && bCanHit && bTimeCheck && bRangeCheck && bPK) { // 슬레이어일 경우에만 이펙트 오브젝트를 생성한다. if (pTargetCreature->isSlayer()) { EffectBloodDrain* pEffectBloodDrain = new EffectBloodDrain(pTargetCreature); pEffectBloodDrain->setLevel(pVampire->getLevel()); pEffectBloodDrain->setDeadline(BLOODDRAIN_DURATION); // 3일?? pTargetCreature->addEffect(pEffectBloodDrain); pEffectBloodDrain->create(pTargetCreature->getName()); _GCBloodDrainOK2.addShortData(MODIFY_EFFECT_STAT, Effect::EFFECT_CLASS_BLOOD_DRAIN); // 타겟이 뭐든 플래그는 건다. pTargetCreature->setFlag(Effect::EFFECT_CLASS_BLOOD_DRAIN); Slayer* pTargetSlayer = dynamic_cast<Slayer*>(pTargetCreature); SLAYER_RECORD prev; pTargetSlayer->getSlayerRecord(prev); pTargetSlayer->initAllStat(); pTargetSlayer->sendRealWearingInfo(); pTargetSlayer->addModifyInfo(prev, _GCBloodDrainOK2); // 로그를 남긴다. //log(LOG_BLOODDRAINED, pTargetCreature->getName(), pVampire->getName()); } // 아우스터즈의 경우엔..... -_-; 제한시간 없는 이펙트를 생성한다. 엄밀히 말해 제한시간이 없는 건 아니지만.. // else if (pTargetCreature->isOusters() ) // { // EffectBloodDrain* pEffectBloodDrain = new EffectBloodDrain(pTargetCreature); // pEffectBloodDrain->setLevel(pVampire->getLevel()); // pTargetCreature->addEffect(pEffectBloodDrain); // pEffectBloodDrain->create(pTargetCreature->getName()); // _GCBloodDrainOK2.addShortData(MODIFY_EFFECT_STAT, Effect::EFFECT_CLASS_BLOOD_DRAIN); // // // 타겟이 뭐든 플래그는 건다. // pTargetCreature->setFlag(Effect::EFFECT_CLASS_BLOOD_DRAIN); // // Sight_t oldSight = pTargetCreature->getSight(); // Sight_t newSight = pTargetCreature->getEffectedSight(); // // if (oldSight != newSight ) // { // pTargetCreature->setSight(newSight); // pZone->updateScan(pTargetCreature, oldSight, pTargetCreature->getSight()); // _GCBloodDrainOK2.addShortData(MODIFY_VISION, pTargetCreature->getSight()); // // GCChangeDarkLight gcChangeDarkLight; // gcChangeDarkLight.setDarkLevel(15); // gcChangeDarkLight.setLightLevel(newSight); // pTargetCreature->getPlayer()->sendPacket(&gcChangeDarkLight); // } // } // 타겟이 뭐든 플래그는 건다. pTargetCreature->setFlag(Effect::EFFECT_CLASS_BLOOD_DRAIN); // 올릴 경험치량을 계산한다. Exp_t Exp = computeCreatureExp(pTargetCreature, BLOODDRAIN_EXP); int targetLevel = 0; int targetMaxHP = 0; // 페임을 올려준다. if (pTargetCreature->isSlayer()) { //increaseFame(pVampire, Exp); Slayer* pTargetSlayer = dynamic_cast<Slayer*>(pTargetCreature); targetLevel = pTargetSlayer->getHighestSkillDomainLevel(); targetMaxHP = pTargetSlayer->getHP(ATTR_MAX); } else if (pTargetCreature->isVampire()) { //increaseFame(pVampire, Exp); Vampire* pTargetVampire = dynamic_cast<Vampire*>(pTargetCreature); targetLevel = pTargetVampire->getLevel(); targetMaxHP = pTargetVampire->getHP(ATTR_MAX); } else if (pTargetCreature->isOusters()) { //increaseFame(pOusters, Exp); Ousters* pTargetOusters = dynamic_cast<Ousters*>(pTargetCreature); targetLevel = pTargetOusters->getLevel(); targetMaxHP = pTargetOusters->getHP(ATTR_MAX); } else if (pTargetCreature->isMonster()) { Monster* pMonster = dynamic_cast<Monster*>(pTargetCreature); Timeval NextTurn = pMonster->getNextTurn(); Timeval DelayTurn; DelayTurn.tv_sec = 4; DelayTurn.tv_usec = 500000; pMonster->addAccuDelay(DelayTurn); pMonster->addEnemy(pVampire); targetLevel = pMonster->getLevel(); targetMaxHP = pMonster->getHP(ATTR_MAX); } shareVampExp(pVampire, Exp, _GCBloodDrainOK1); // 흡혈을 하게 되면 흡혈한 사람의 체력이 올라간다. // Mephisto이펙트가 걸려있으면 HP는 안 올라간다. if (!pVampire->isFlag(Effect::EFFECT_CLASS_MEPHISTO)) { HP_t HealPoint = (Exp==0? computeBloodDrainHealPoint(pTargetCreature, BLOODDRAIN_EXP) : Exp); HP_t CurrentHP = pVampire->getHP(); HP_t MaxHP = pVampire->getHP(ATTR_MAX); HP_t NewHP = min((int)MaxHP , (int)CurrentHP + (int)HealPoint); // 은 데미지 관련 처리를 해 준다. Silver_t newSilverDamage = max(0, (int)pVampire->getSilverDamage()-(int)HealPoint); pVampire->saveSilverDamage(newSilverDamage); _GCBloodDrainOK1.addShortData(MODIFY_SILVER_DAMAGE, newSilverDamage); // 뱀파이어의 HP를 세팅한다. pVampire->setHP(NewHP); GCStatusCurrentHP gcStatusCurrentHP; gcStatusCurrentHP.setObjectID(pVampire->getObjectID()); gcStatusCurrentHP.setCurrentHP(NewHP); pZone->broadcastPacket(pVampire->getX(), pVampire->getY(), &gcStatusCurrentHP, pVampire); _GCBloodDrainOK1.addShortData(MODIFY_CURRENT_HP, NewHP); } // 흡혈을 당한 애는 HP가 줄어든다. // 대상이 내 레벨보다 높다면.. MaxHP의 10~15% damage // by sigi. 2002.9.14 int drainDamage = 0; int myLevel = pVampire->getLevel(); if (targetLevel > myLevel) { drainDamage = targetMaxHP * (rand()%6+10) / 100; } else { // 레벨 5차이마다 1%씩 더~ int damagePercent = min(30, (rand()%6+10+(myLevel-targetLevel))); drainDamage = targetMaxHP * damagePercent / 100; } if (drainDamage > 0) { //decreaseHP(pZone, pTargetCreature, drainDamage, pVampire->getObjectID()); EffectDecreaseHP* pEffect = new EffectDecreaseHP(pTargetCreature); pEffect->setPoint(drainDamage); pEffect->setDeadline(20); // 2초 후 pEffect->setUserObjectID(pVampire->getObjectID()); pTargetCreature->addEffect(pEffect); pTargetCreature->setFlag(Effect::EFFECT_CLASS_DECREASE_HP); } pVampire->getGQuestManager()->blooddrain(); // 흡혈시에도 성향 바뀜 // by sigi. 2002.12.16 // EffectDecreaseHP에서 HP가 닳아서 0이 되어야하는 경우가 있어서 // EffectDecreaseHP::unaffect()로 옮긴다. //computeAlignmentChange(pTargetCreature, drainDamage, pVampire, NULL, &_GCBloodDrainOK1); _GCBloodDrainOK1.setObjectID(TargetObjectID); _GCBloodDrainOK3.setObjectID(pVampire->getObjectID()); _GCBloodDrainOK3.setTargetObjectID (TargetObjectID); pPlayer->sendPacket(&_GCBloodDrainOK1); if (pTargetCreature != NULL && pTargetCreature->isPC()) { Player* pTargetPlayer = pTargetCreature->getPlayer(); if (pTargetPlayer != NULL) { _GCBloodDrainOK2.setObjectID(pVampire->getObjectID()); // _GCBloodDrainOK2.addLongData(MODIFY_DURATION, BLOODDRAIN_DURATION); pTargetPlayer->sendPacket(&_GCBloodDrainOK2); } } list<Creature *> cList; cList.push_back(pTargetCreature); cList.push_back(pVampire); pZone->broadcastPacket(pVampire->getX(), pVampire->getY(), &_GCBloodDrainOK3 , cList); } else { executeSkillFailNormal(pVampire, getSkillType(), pTargetCreature); } } catch (Throwable & t) { executeSkillFailException(pVampire, getSkillType()); } //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End(vampire)" << endl; __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 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 }