Beispiel #1
0
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);
}
Beispiel #2
0
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;
        }
    }
}