• 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!

Feature Protection Time

margoh

{{ user.title }}
Joined
Apr 1, 2013
Messages
806
Solutions
18
Reaction score
350
Hello.

How does it work:
  • If you login you get 10 seconds (configurable) of protection.
  • If you move you lose protection.
  • If you push yourself, you lose protection.
  • If you attack creature, you lose protection.
  • If times runs out, monsters attacks you.
combat.cpp in Combat::canDoCombat(Creature* attacker, Creature* target) before } else if (attacker->getMonster()) { add:
C++:
// protection time
    if (attackerPlayer->getProtectionTime() > 0) {
        Player* player = attacker->getPlayer();
        player->setProtectionTime(0);
    }
creature.cpp in Creature::onCreatureMove before if (creature == attackedCreature || (creature == this && attackedCreature)) { add:
C++:
// protection time
    if (creature->getPlayer()) {
        if (creature->getPlayer()->getProtectionTime() > 0) {
            creature->getPlayer()->setProtectionTime(0);
        }
    }
iologindata.cpp in IOLoginData::loadPlayerById and IOLoginData::loadPlayerByName after `direction` add:
C++:
, `protection_time`
After player->direction = static_cast<Direction> (result->getNumber<uint16_t>("direction")); add:
C++:
player->protectionTime = result->getNumber<uint16_t>("protection_time");
After query << "`direction` = " << static_cast<uint16_t> (player->getDirection()) << ','; add:
C++:
query << "`protection_time` = " << g_config.getNumber(ConfigManager::PROTECTION_TIME) << ',';
configmanager.cpp under integer[DEPOT_PREMIUM_LIMIT] = getGlobalNumber(L, "depotPremiumLimit", 10000); add:
C++:
integer[PROTECTION_TIME] = getGlobalNumber(L, "protectionTime", 10);
configmanager.h under DEPOT_PREMIUM_LIMIT, add:
C++:
PROTECTION_TIME,
luascript.cpp under registerEnumIn("configKeys", ConfigManager::PLAYER_CONSOLE_LOGS) add:
C++:
registerEnumIn("configKeys", ConfigManager::PROTECTION_TIME)
Under registerMethod("Player", "getStoreInbox", LuaScriptInterface::luaPlayerGetStoreInbox); add:
C++:
registerMethod("Player", "getProtectionTime", LuaScriptInterface::luaPlayerGetProtectionTime);
registerMethod("Player", "setProtectionTime", LuaScriptInterface::luaPlayerSetProtectionTime);
After function int LuaScriptInterface::luaPlayerGetStoreInbox(lua_State* L) add:
C++:
int LuaScriptInterface::luaPlayerGetProtectionTime(lua_State* L)
{
    // player:getProtectionTime()
    Player* player = getUserdata<Player>(L, 1);
    if (player) {
        lua_pushnumber(L, player->getProtectionTime());
    } else {
        lua_pushnil(L);
    }
    return 1;
}

int LuaScriptInterface::luaPlayerSetProtectionTime(lua_State* L)
{
    // player:setProtectionTime(time)
    Player* player = getUserdata<Player>(L, 1);
    if (!player) {
        lua_pushnil(L);
        return 1;
    }

    uint16_t time = getNumber<uint16_t>(L, 2);
    player->setProtectionTime(time);
    pushBoolean(L, true);
    return 1;
}
luascript.h after static int lauPlayerGetStoreInbox(lua_State* L); add:
C++:
static int luaPlayerGetProtectionTime(lua_State* L);
static int luaPlayerSetProtectionTime(lua_State* L);
monster.cpp in function bool Monster::selectTarget(Creature* creature) under first check add:
C++:
int32_t storage = g_config.getNumber(ConfigManager::PROTECTION_TIME_STORAGE);
int32_t value;
if (player)) {
    if (player->getProtectionTime() > 0) {
        return false;
    }
}
player.cpp inside void Player::onThink(uint32_t interval) under sendPing() add:
C++:
//Protection time down
if (this->getProtectionTime() > 0) {
        this->setProtectionTime(this->getProtectionTime() - 1);
}
player.h after virtual void setMaxMana(int32_t _manaMax) { manaMax = _manaMax; } or other function, add:
C++:
uint16_t getProtectionTime() const { return protectionTime; }
void setProtectionTime(uint16_t newProtectionTime) { protectionTime = newProtectionTime; }
After uint16_t maxWriteLen = 0; add:
C++:
uint16_t protectionTime = 10;
data/migrations/30.lua edit to:
Lua:
function onUpdateDatabase()
    db.query("ALTER TABLE `players` ADD `protection_time` int(11) NOT NULL DEFAULT 0")
    return true
end
Inside data/migrations create file 31.lua and paste:
Lua:
function onUpdateDatabase()
    return false
end

config.lua wherever add:
Lua:
protectionTime = 10 -- Time in seconds

Drop protection_time.lua inside data/scripts

Tested on TFS 1.4.2.
Cheers.


Extra: monster.cpp in Monster::onThinkTarget(uint32_t interval) under if (!isSummon()) { add:
C++:
// protection time
if (this->getAttackedCreature()) {
    if (getAttackedCreature()->getPlayer()->getProtectionTime() > 0) {
        setAttackedCreature(nullptr);
        updateTargetList();
        followCreature = false;
    }
}
If we set protectionTime on the fly, monster stops attacking player.
 
Last edited:
Hello.

How does it work:
  • If you login you get 10 seconds (configurable) of protection.
  • If you move you lose protection.
  • If you push yourself, you lose protection.
  • If you attack creature, you lose protection.
  • If times runs out, monsters attacks you.
configmanager.cpp under integer[DEPOT_PREMIUM_LIMIT] = getGlobalNumber(L, "depotPremiumLimit", 10000); add:
C++:
integer[PROTECTION_TIME_STORAGE] = getGlobalNumber(L, "protectionTimeStorage", 1000);
integer[PROTECTION_TIME] = getGlobalNumber(L, "protectionTime", 10);
configmanager.h under DEPOT_PREMIUM_LIMIT, add:
C++:
PROTECTION_TIME_STORAGE,
PROTECTION_TIME,
luascript.cpp under registerEnumIn("configKeys", ConfigManager::PLAYER_CONSOLE_LOGS) add:
C++:
registerEnumIn("configKeys", ConfigManager::PROTECTION_TIME_STORAGE)
registerEnumIn("configKeys", ConfigManager::PROTECTION_TIME)
monster.cpp in function bool Monster::selectTarget(Creature* creature) under first check add:
C++:
int32_t storage = g_config.getNumber(ConfigManager::PROTECTION_TIME_STORAGE);
int32_t value;
if (player && player->getStorageValue(storage, value)) {
    if (value > 0) {
        return false;
    }
}
player.cpp in function void Player::onWalk(Direction& dir) before Creature::onWalk(dir); add:
C++:
int32_t storage = g_config.getNumber(ConfigManager::PROTECTION_TIME_STORAGE);
int32_t value;
if (player && player->getStorageValue(storage, value)) {
    if (value > 0) {
        return false;
    }
}
As I have no idea how to make onThink scripts working, feel free to do so and if you do, skip next step.
Inside void Player::onThink(uint32_t interval) under sendPing() add:
C++:
//Protection time down
int32_t storage = g_config.getNumber(ConfigManager::PROTECTION_TIME_STORAGE);
int32_t value;
if (this->getStorageValue(storage, value)) {
    if (value > 0) {
        this->addStorageValue(storage, value - 1);
    }
}
config.lua wherever add:
Lua:
protectionTimeStorage = 1000 -- Set your own storage
protectionTime = 10 -- Time in seconds
events.xml enable:
XML:
<event class="Creature" method="onTargetCombat" enabled="1" />
<event class="Player" method="onMoveCreature" enabled="1" />

Drop protection_time.lua inside data/scripts

Tested on TFS 1.4.2.
Cheers.
Hello, is it possible to reduce all this to an item that you use and lasts 5 seconds where you are immune to all kinds of attacks and then the item is spent and disappears from the player's inventory?
 
please no revscript :(
Why? Shouldn't it be easy to convert to non revscript?
Hello, is it possible to reduce all this to an item that you use and lasts 5 seconds where you are immune to all kinds of attacks and then the item is spent and disappears from the player's inventory?
I think what you want works different way, as they can still attack you, and this makes monsters ignore you for X time. Best bet would be make a script that sets physical and magical immunity to 100%, and after that 5 seconds changes it back to 0% or whatever percent player may have.
 
Yup, you are right, to be honest I didn't care about it. But I updated it, reported first post for update.
 
Yup, you are right, to be honest I didn't care about it. But I updated it, reported first post for update.

its a very wrong comment from oen. it does not need any changes.

using storage here is no problem. u can have thousands of players online checking storages every second. it will not use a lot of power. Better focus on things that actually ruin ur servers performance and crash ur servers, and even clients XDDD (😏 @oen342)
And storage is good for some uses. instead of adding new field in player userdata we can just use a new storage number and it can be straight away manipulated from lua and getting it from database. And spamming storage is no problem. you can spam thousands of storagerequests on every player even with thousands online, it will not take much power.
 
its a very wrong comment from oen. it does not need any changes.

using storage here is no problem. u can have thousands of players online checking storages every second. it will not use a lot of power. Better focus on things that actually ruin ur servers performance and crash ur servers, and even clients XDDD (😏 @oen342)
And storage is good for some uses. instead of adding new field in player userdata we can just use a new storage number and it can be straight away manipulated from lua and getting it from database. And spamming storage is no problem. you can spam thousands of storagerequests on every player even with thousands online, it will not take much power.
Please don't listen to this troll, he has no idea what he is talking about.
 
don't storages make it possible to set for player his own protection time? like: some players would have 7s some 10s for example? anyway, that's for most cases useless and agreed that it's better written without storages.
 
Some typo, don't add
C++:
int32_t storage = g_config.getNumber(ConfigManager::PROTECTION_TIME_STORAGE);
int32_t value;
In step: monster.cpp in function bool Monster::selectTarget(Creature* creature) under first check.
And there is no need to drop any file.
 
if the player is summoned when he logs in and there is a monster on the screen the server crashes
 
Please don't listen to this troll, he has no idea what he is talking about.
trolll btw.
lets not comment on obvious crash, lets comment about insiginicant performance improvements
 
I tried to force a crash, yet I wasn't successful. The only thing I have noticed, after teleporting player, was monster noticing player and started to target player, yet not trying to move to target like it should be.
 
I tried to force a crash, yet I wasn't successful. The only thing I have noticed, after teleporting player, was monster noticing player and started to target player, yet not trying to move to target like it should be.
The crash hazard is here:

Extra: monster.cpp in Monster::onThinkTarget(uint32_t interval) under if (!isSummon()) { add:
C++:
// protection time
if (this->getAttackedCreature()) {
    if (getAttackedCreature()->getPlayer()->getProtectionTime() > 0) {
        setAttackedCreature(nullptr);
        updateTargetList();
        followCreature = false;
    }
}
If we set protectionTime on the fly, monster stops attacking player.

Specifically this statement: if (getAttackedCreature()->getPlayer()->getProtectionTime() > 0) {

It is not guaranteed that the attacked creature is a player (for example it could be targeting a player summon), in that case getPlayer() would return a nullpointer, which you then call getProtectionTime on, and this would be a nullpointer dereference and crash the server
 
The crash hazard is here:



Specifically this statement: if (getAttackedCreature()->getPlayer()->getProtectionTime() > 0) {

It is not guaranteed that the attacked creature is a player (for example it could be targeting a player summon), in that case getPlayer() would return a nullpointer, which you then call getProtectionTime on, and this would be a nullpointer dereference and crash the server
that the crash shows exactly this line
 
that the crash shows exactly this line
It should be:
C++:
if (getAttackedCreature() && getAttackedCreature()->getPlayer() && getAttackedCreature()->getPlayer()->getProtectionTime() > 0) {
    setAttackedCreature(nullptr);
    updateTargetList();
    followCreature = false;
}
3 IFs:
1. Is there attacked creature at all?
2. Is attacked creature a player?
3. Is attacked player protection time higher than zero?
 
It should be:
C++:
if (getAttackedCreature() && getAttackedCreature()->getPlayer() && getAttackedCreature()->getPlayer()->getProtectionTime() > 0) {
    setAttackedCreature(nullptr);
    updateTargetList();
    followCreature = false;
}
3 IFs:
1. Is there attacked creature at all?
2. Is attacked creature a player?
3. Is attacked player protection time higher than zero?
fixed it!
 
Back
Top