• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

TFS 1.X+ tfs 1.5 by Nekiro 8.6 atack wepon distance

Michcol94

Member
Joined
Sep 2, 2021
Messages
105
Reaction score
18
When he attacks with a ranged weapon that has no ammunition and I stand still is ok, but when he attacks with a weapon, when I move, the weapon attack stops, it is not smooth and slows down. Let me add that I have a modification of the source code to increase the attack speed based on skill. The problem seems to me to be related to the source code of the engine. Please help.
 
When he attacks with a ranged weapon that has no ammunition and I stand still is ok, but when he attacks with a weapon, when I move, the weapon attack stops, it is not smooth and slows down. Let me add that I have a modification of the source code to increase the attack speed based on skill. The problem seems to me to be related to the source code of the engine. Please help.
it could be the modification you made
 
player.cpp by my special modyfication
C++:
uint32_t Player::getAttackSpeed() const
{
    uint32_t baseSpeed = 3000; // podstawowa prędkość ataku (3 sekundy)
    uint32_t minAttackSpeed = 100; // minimalna prędkość ataku (10 ataków na sekundę)
    uint32_t skillAxe = getSkillLevel(SKILL_AXE); // poziom umiejętności w używaniu broni typu axe

    // Maksymalny modyfikator prędkości ataku
    uint32_t maxSpeedModifier = 2900;

    // Maksymalny poziom umiejętności
    uint32_t maxSkillLevel = 170;

    // Oblicz modyfikator prędkości ataku
    uint32_t speedModifier = skillAxe * (maxSpeedModifier / maxSkillLevel);

    // Ogranicz modyfikator prędkości ataku do wartości maksymalnej
    if (speedModifier > maxSpeedModifier) {
        speedModifier = maxSpeedModifier;
    }

    const Item* weapon = getWeapon(true);

    if (!weapon || weapon->getAttackSpeed() == 0 || skillAxe >= maxSkillLevel) {
        uint32_t attackSpeed = baseSpeed - speedModifier;
        return attackSpeed < minAttackSpeed ? minAttackSpeed : attackSpeed;
    }

    uint32_t attackSpeed = weapon->getAttackSpeed() - speedModifier;
    return attackSpeed < minAttackSpeed ? minAttackSpeed : attackSpeed;
}
player.h
C++:
uint32_t getAttackSpeed() const;
I'm not sure if that's all but I guess so about Attack Speed.

Now config.lua
Lua:
-- Combat settings
-- NOTE: valid values for worldType are: "pvp", "no-pvp" and "pvp-enforced"
worldType = "pvp"
hotkeyAimbotEnabled = true
protectionLevel = 1
killsToRedSkull = 3
killsToBlackSkull = 6
pzLocked = 60000
removeChargesFromRunes = true
removeChargesFromPotions = true
removeWeaponAmmunition = true
removeWeaponCharges = true
timeToDecreaseFrags = 24 * 60 * 60
whiteSkullTime = 15 * 60
stairJumpExhaustion = 2000
experienceByKillingPlayers = false
expFromPlayersLevelRange = 75
pzLockSkullAttacker = false

-- Connection Config
-- NOTE: maxPlayers set to 0 means no limit
-- NOTE: allowWalkthrough is only applicable to players
ip = ""
bindOnlyGlobalAddress = false
loginProtocolPort = 7171
gameProtocolPort = 7172
statusProtocolPort = 7171
maxPlayers = 0
motd = "Welcome to Dragob Ball Legacy!"
onePlayerOnlinePerAccount = true
allowClones = false
allowWalkthrough = true
serverName = "Dragob Ball Legacy"
statusTimeout = 5000
replaceKickOnLogin = true
maxPacketsPerSecond = 25

-- Deaths
-- NOTE: Leave deathLosePercent as -1 if you want to use the default
-- death penalty formula. For the old formula, set it to 10. For
-- no skill/experience loss, set it to 0.
deathLosePercent = -1

-- Houses
-- NOTE: set housePriceEachSQM to -1 to disable the ingame buy house functionality
-- NOTE: valid values for houseRentPeriod are: "daily", "weekly", "monthly", "yearly"
-- use any other value to disable the rent system
housePriceEachSQM = 1000
houseRentPeriod = "never"
houseOwnedByAccount = false
houseDoorShowPrice = true
onlyInvitedCanMoveHouseItems = true

-- Item Usage
timeBetweenActions = 200
timeBetweenExActions = 1000

-- Map
-- NOTE: set mapName WITHOUT .otbm at the end
mapName = "forgotten"
mapAuthor = "Komic"

-- Market
marketOfferDuration = 30 * 24 * 60 * 60
premiumToCreateMarketOffer = true
checkExpiredMarketOffersEachMinutes = 60
maxMarketOffersAtATimePerPlayer = 100

-- MySQL


-- Misc.
-- NOTE: classicAttackSpeed set to true makes players constantly attack at regular
-- intervals regardless of other actions such as item (potion) use. This setting
-- may cause high CPU usage with many players and potentially affect performance!
-- NOTE: forceMonsterTypesOnLoad loads all monster types on startup to validate them.
-- You can disable it to save some memory if you don't see any errors at startup.
allowChangeOutfit = false
freePremium = false
kickIdlePlayerAfterMinutes = 15
maxMessageBuffer = 4
emoteSpells = false
classicEquipmentSlots = false
classicAttackSpeed = false
showScriptsLogInConsole = false
showOnlineStatusInCharlist = false
yellMinimumLevel = 2
yellAlwaysAllowPremium = false
minimumLevelToSendPrivate = 1
premiumToSendPrivate = false
forceMonsterTypesOnLoad = true
cleanProtectionZones = false
luaItemDesc = false
showPlayerLogInConsole = true

-- VIP and Depot limits
-- NOTE: you can set custom limits per group in data/XML/groups.xml
vipFreeLimit = 20
vipPremiumLimit = 100
depotFreeLimit = 2000
depotPremiumLimit = 10000

-- World Light
-- NOTE: if defaultWorldLight is set to true the world light algorithm will
-- be handled in the sources. set it to false to avoid conflicts if you wish
-- to make use of the function setWorldLight(level, color)
defaultWorldLight = true

-- Server Save
-- NOTE: serverSaveNotifyDuration in minutes
serverSaveNotifyMessage = true
serverSaveNotifyDuration = 5
serverSaveCleanMap = false
serverSaveClose = false
serverSaveShutdown = true

-- Experience stages
-- NOTE: to use a flat experience multiplier, set experienceStages to nil
-- minlevel and multiplier are MANDATORY
-- maxlevel is OPTIONAL, but is considered infinite by default
-- to disable stages, create a stage with minlevel 1 and no maxlevel
experienceStages = {
    { minlevel = 1, maxlevel = 8, multiplier = 7 },
    { minlevel = 9, maxlevel = 20, multiplier = 6 },
    { minlevel = 21, maxlevel = 50, multiplier = 5 },
    { minlevel = 51, maxlevel = 100, multiplier = 4 },
    { minlevel = 101, multiplier = 3 }
}

-- Rates
-- NOTE: rateExp is not used if you have enabled stages above
rateExp = 5
rateSkill = 3
rateLoot = 2
rateMagic = 3
rateSpawn = 1

-- Monster Despawn Config
-- despawnRange is the amount of floors a monster can be from its spawn position
-- despawnRadius is how many tiles away it can be from its spawn position
-- removeOnDespawn will remove the monster if true or teleport it back to its spawn position if false
-- walkToSpawnRadius is the allowed distance that the monster will stay away from spawn position when left with no targets, 0 to disable
deSpawnRange = 2
deSpawnRadius = 50
removeOnDespawn = true
walkToSpawnRadius = 15

-- Stamina
staminaSystem = true

-- Scripts
warnUnsafeScripts = true
convertUnsafeScripts = true

-- Startup
-- NOTE: defaultPriority only works on Windows and sets process
-- priority, valid values are: "normal", "above-normal", "high"
defaultPriority = "high"
startupDatabaseOptimization = false

-- Status Server Information
ownerName = ""
ownerEmail = ""
url = "https://otland.net/"
location = "Sweden"
 
I changed the functions a bit doAttacking in player.cpp and it is a bit better if anyone have any ideas?
orginal code:
C++:
void Player::doAttacking(uint32_t interval) {  
    if (attackedCreature == nullptr) {
       return;  
    }
    if (lastAttack == 0) {
        lastAttack = OTSYS_TIME() - getAttackSpeed() - 1;
    }

    if (hasCondition(CONDITION_PACIFIED)) {
        return;
    }

    if ((OTSYS_TIME() - lastAttack) >= getAttackSpeed()) {
        bool result = false;

        Item* tool = getWeapon();
        const Weapon* weapon = g_weapons->getWeapon(tool);
        uint32_t delay = getAttackSpeed();
        bool classicSpeed = g_config.getBoolean(ConfigManager::CLASSIC_ATTACK_SPEED);

        if (weapon) {
            if (!weapon->interruptSwing()) {
                result = weapon->useWeapon(this, tool, attackedCreature);
            } else if (!classicSpeed && !canDoAction()) {
                delay = getNextActionTime();
            } else {
                result = weapon->useWeapon(this, tool, attackedCreature);
            }
        } else {
            result = Weapon::useFist(this, attackedCreature);
        }

        SchedulerTask* task = createSchedulerTask(std::max<uint32_t>(SCHEDULER_MINTICKS, delay), std::bind(&Game::checkCreatureAttack, &g_game, getID()));
        if (!classicSpeed) {
            setNextActionTask(task, false);
        } else {
            g_scheduler.addEvent(task);
        }

        if (result) {
            lastAttack = OTSYS_TIME();
        }
    }
}

uint64_t Player::getGainedExperience(Creature* attacker) const
{
    if (g_config.getBoolean(ConfigManager::EXPERIENCE_FROM_PLAYERS)) {
        Player* attackerPlayer = attacker->getPlayer();
        if (attackerPlayer && attackerPlayer != this && skillLoss && std::abs(static_cast<int32_t>(attackerPlayer->getLevel() - level)) <= g_config.getNumber(ConfigManager::EXP_FROM_PLAYERS_LEVEL_RANGE)) {
            return std::max<uint64_t>(0, std::floor(getLostExperience() * getDamageRatio(attacker) * 0.75));
        }
    }
    return 0;
}
change my edit code :
C++:
void Player::doAttacking(uint32_t)
{
    if (lastAttack == 0) {
        lastAttack = OTSYS_TIME() - getAttackSpeed() - 1;
    }

    if (hasCondition(CONDITION_PACIFIED)) {
        return;
    }

    if ((OTSYS_TIME() - lastAttack) >= getAttackSpeed()) {
        bool result = false;

        Item* tool = getWeapon();
        const Weapon* weapon = g_weapons->getWeapon(tool);

        if (weapon) {
            if (!weapon->interruptSwing() || weapon->useWeapon(this, tool, attackedCreature)) {
                result = weapon->useWeapon(this, tool, attackedCreature);
            }
        }
        else {
            result = Weapon::useFist(this, attackedCreature);
        }

        uint32_t delay = getAttackSpeed();
        bool classicSpeed = g_config.getBoolean(ConfigManager::CLASSIC_ATTACK_SPEED);
        SchedulerTask* task = createSchedulerTask(std::max<uint32_t>(SCHEDULER_MINTICKS, delay), std::bind(&Game::checkCreatureAttack, &g_game, getID()));
        if (!classicSpeed) {
            setNextActionTask(task, false);
        }
        else {
            g_scheduler.addEvent(task);
        }

        if (result) {
            lastAttack = OTSYS_TIME();
        }
    }
}



uint64_t Player::getGainedExperience(Creature* attacker) const
{
    if (g_config.getBoolean(ConfigManager::EXPERIENCE_FROM_PLAYERS)) {
        Player* attackerPlayer = attacker->getPlayer();
        if (attackerPlayer && attackerPlayer != this && skillLoss && std::abs(static_cast<int32_t>(attackerPlayer->getLevel() - level)) <= g_config.getNumber(ConfigManager::EXP_FROM_PLAYERS_LEVEL_RANGE)) {
            return std::max<uint64_t>(0, std::floor(getLostExperience() * getDamageRatio(attacker) * 0.75));
        }
    }
    return 0;
}
Post automatically merged:

Now working.
changed doAttacking:
C++:
void Player::doAttacking(uint32_t interval) { 
   if (attackedCreature == nullptr) {  
      return;  
  }
    if (hasCondition(CONDITION_PACIFIED)) {
        return;
    }

    bool result = false;

    Item* tool = getWeapon();
    const Weapon* weapon = g_weapons->getWeapon(tool);

    if (weapon) {
        if (!weapon->interruptSwing() || weapon->useWeapon(this, tool, attackedCreature)) {
            result = weapon->useWeapon(this, tool, attackedCreature);
        }
    }
    else {
        result = Weapon::useFist(this, attackedCreature);
    }

    uint32_t delay = getAttackSpeed();
    bool classicSpeed = g_config.getBoolean(ConfigManager::CLASSIC_ATTACK_SPEED);
    SchedulerTask* task = createSchedulerTask(std::max<uint32_t>(SCHEDULER_MINTICKS, delay), std::bind(&Game::checkCreatureAttack, &g_game, getID()));
    if (!classicSpeed) {
        setNextActionTask(task, false);
    }
    else {
        g_scheduler.addEvent(task);
    }

    if (result) {
        lastAttack = OTSYS_TIME();
    }
}
and changed method onWalk:
C++:
void Player::onWalk(Direction& dir)
{
    Creature::onWalk(dir);
    setNextActionTask(nullptr);
    setNextAction(OTSYS_TIME() + getStepDuration(dir));
    if (attackedCreature) {
        doAttacking(0);
    }
}
Can these changes cause any problems and generate any errors or, for example, engine crasch?
 
Last edited:
Back
Top