void CUser::Attack(Packet & pkt) { int16 sid = -1, tid = -1, damage, delaytime, distance; uint8 bType, bResult = 0; Unit * pTarget = nullptr; pkt >> bType >> bResult >> tid >> delaytime >> distance; // delaytime = delaytime / 100.0f; // distance = distance / 10.0f; if (isIncapacitated()) return; if (isInSafetyArea()) return; if (m_bInvisibilityType != INVIS_NONE) { CMagicProcess::RemoveStealth(this, INVIS_DISPEL_ON_MOVE); CMagicProcess::RemoveStealth(this, INVIS_DISPEL_ON_ATTACK); } // If you're holding a weapon, do a client-based (ugh, do not trust!) delay check. _ITEM_TABLE *pTable = GetItemPrototype(RIGHTHAND); if (pTable != nullptr) { if (delaytime < (pTable->m_sDelay + 10) // client adds 0.1 onto the interval (0.1 of 100 is 10) || distance > pTable->m_sRange) return; } // Empty handed. else if (delaytime < 100) return; pTarget = g_pMain->GetUnitPtr(tid); bResult = ATTACK_FAIL; if (pTarget != nullptr && isInAttackRange(pTarget) && CanAttack(pTarget)) { if (isAttackable(pTarget) && CanCastRHit(GetSocketID())) { if (isInTempleEventZone()) if (GetUserGroup() != -1 && !isSameUserGroup(pTarget)) return; CUser *pUser = g_pMain->GetUserPtr(GetSocketID()); if (pUser != nullptr) pUser->m_RHitRepeatList.insert(std::make_pair(GetSocketID(), UNIXTIME)); damage = GetDamage(pTarget); // Can't use R attacks in the Snow War. if (GetZoneID() == ZONE_SNOW_BATTLE && g_pMain->m_byBattleOpen == SNOW_BATTLE) damage = 0; if (damage > 0) { pTarget->HpChange(-damage, this); if (pTarget->isDead()) bResult = ATTACK_TARGET_DEAD; else bResult = ATTACK_SUCCESS; // Every attack takes a little of your weapon's durability. ItemWoreOut(ATTACK, damage); // Every hit takes a little of the defender's armour durability. if (pTarget->isPlayer()) TO_USER(pTarget)->ItemWoreOut(DEFENCE, damage); } } } Packet result(WIZ_ATTACK, bType); result << bResult << GetSocketID() << tid; SendToRegion(&result); }
void UnitBase::engageTarget() { if(target && (target.getObjPointer() == NULL)) { // the target does not exist anymore releaseTarget(); return; } if(target && (target.getObjPointer()->isActive() == false)) { // the target changed its state to inactive releaseTarget(); return; } if(target && !targetFriendly && !canAttack(target.getObjPointer())) { // the (non-friendly) target cannot be attacked anymore releaseTarget(); return; } if(target && !targetFriendly && !forced && !isInAttackRange(target.getObjPointer())) { // the (non-friendly) target left the attack mode range (and we were not forced to attack it) releaseTarget(); return; } if(target) { // we have a target unit or structure Coord targetLocation = target.getObjPointer()->getClosestPoint(location); if(destination != targetLocation) { // the location of the target has moved // => recalculate path clearPath(); } targetDistance = blockDistance(location, targetLocation); Sint8 newTargetAngle = lround(8.0f/256.0f*destinationAngle(location, targetLocation)); if(newTargetAngle == 8) { newTargetAngle = 0; } if(bFollow) { // we are following someone setDestination(targetLocation); return; } if(targetDistance > getWeaponRange()) { // we are not in attack range // => follow the target setDestination(targetLocation); return; } // we are in attack range if(targetFriendly && !forced) { // the target is friendly and we only attack these if were forced to do so return; } if(goingToRepairYard) { // we are going to the repair yard // => we do not need to change the destination targetAngle = INVALID; } else if(attackMode == CAPTURE) { // we want to capture the target building setDestination(targetLocation); targetAngle = INVALID; } else if(isTracked() && target.getObjPointer()->isInfantry() && currentGameMap->tileExists(targetLocation) && !currentGameMap->getTile(targetLocation)->isMountain() && forced) { // we squash the infantry unit because we are forced to setDestination(targetLocation); targetAngle = INVALID; } else { // we decide to fire on the target thus we can stop moving setDestination(location); targetAngle = newTargetAngle; } if(getCurrentAttackAngle() == newTargetAngle) { attack(); } } else if(attackPos) { // we attack a position targetDistance = blockDistance(location, attackPos); Sint8 newTargetAngle = lround(8.0f/256.0f*destinationAngle(location, attackPos)); if(newTargetAngle == 8) { newTargetAngle = 0; } if(targetDistance <= getWeaponRange()) { // we are in weapon range thus we can stop moving setDestination(location); targetAngle = newTargetAngle; if(getCurrentAttackAngle() == newTargetAngle) { attack(); } } else { targetAngle = INVALID; } } }