We need more information than just this issue. We need to know did you alter the sources and if so all the changes you made? Are you using custom scripts? What version of TFS is it? You can't just say 1.x because they differ from distribution to distribution. The more information you can provide the easier it is for someone to help you find a solution.Hi
So i have this weird problem when player dies mana goes to zero and health increase randomly. How to fix it?
Yes i did some source changes but they had nothing to do with health/mana all i did is some color changes and simple stuff like this that has nothing to do with health. My scripts are not custom pretty much my server is still default i haven't done anything crazy without transformation system. I'm using TFS 1.2 downgraded by ninja for 860 protocolWe need more information than just this issue. We need to know did you alter the sources and if so all the changes you made? Are you using custom scripts? What version of TFS is it? You can't just say 1.x because they differ from distribution to distribution. The more information you can provide the easier it is for someone to help you find a solution.
There is your problem right there "I'm using TFS 1.2 downgraded by ninja for 860 protocol"Yes i did some source changes but they had nothing to do with health/mana all i did is some color changes and simple stuff like this that has nothing to do with health. My scripts are not custom pretty much my server is still default i haven't done anything crazy without transformation system. I'm using TFS 1.2 downgraded by ninja for 860 protocol
Lul dont say that i have to pick new tfs? Just because its downgraded 1.2? A lot of otland people are using downgraded ninja edit so maybe they can share solutionThere is your problem right there "I'm using TFS 1.2 downgraded by ninja for 860 protocol"
This is the server. You can look to the source here and other stuff because its the same stuff what i haveIt is uncommon behavior.
We just aren't able to help you as long we don't know what and where you (or someone) made changes in source or added some custom lua script (or changed some already existing)
You need to provide those info or give someone full access to your server files (not recommended)
Anyway for blind analysis I can suggest looking into void Player::death(Creature* lastHitCreature) in player.cpp (death function setting player stats after death) or any Lua script that executes while player dies.
void Player::death(Creature* _lastHitCreature)
{
loginPosition = town->getTemplePosition();
if (skillLoss) {
//Magic level loss
uint64_t sumMana = 0;
uint64_t lostMana = 0;
//sum up all the mana
for (uint32_t i = 1; i <= magLevel; ++i) {
sumMana += vocation->getReqMana(i);
}
sumMana += manaSpent;
double deathLossPercent = getLostPercent();
lostMana = static_cast<uint64_t>(sumMana * deathLossPercent);
while (lostMana > manaSpent && magLevel > 0) {
lostMana -= manaSpent;
manaSpent = vocation->getReqMana(magLevel);
magLevel--;
}
manaSpent -= lostMana;
uint64_t nextReqMana = vocation->getReqMana(magLevel + 1);
if (nextReqMana > vocation->getReqMana(magLevel)) {
magLevelPercent = Player::getPercentLevel(manaSpent, nextReqMana);
} else {
magLevelPercent = 0;
}
//Skill loss
for (uint8_t i = SKILL_FIRST; i <= SKILL_LAST; ++i) { //for each skill
uint64_t sumSkillTries = 0;
for (uint16_t c = 11; c <= skills[i].level; ++c) { //sum up all required tries for all skill levels
sumSkillTries += vocation->getReqSkillTries(i, c);
}
sumSkillTries += skills[i].tries;
uint32_t lostSkillTries = static_cast<uint32_t>(sumSkillTries * deathLossPercent);
while (lostSkillTries > skills[i].tries) {
lostSkillTries -= skills[i].tries;
if (skills[i].level <= 10) {
skills[i].level = 10;
skills[i].tries = 0;
lostSkillTries = 0;
break;
}
skills[i].tries = vocation->getReqSkillTries(i, skills[i].level);
skills[i].level--;
}
skills[i].tries = std::max<int32_t>(0, skills[i].tries - lostSkillTries);
skills[i].percent = Player::getPercentLevel(skills[i].tries, vocation->getReqSkillTries(i, skills[i].level));
}
//Level loss
uint64_t expLoss = static_cast<uint64_t>(experience * deathLossPercent);
g_events->eventPlayerOnLoseExperience(this, expLoss);
if (expLoss != 0) {
uint32_t oldLevel = level;
if (vocation->getId() == VOCATION_NONE || level > 7) {
experience -= expLoss;
}
while (level > 1 && experience < Player::getExpForLevel(level)) {
--level;
healthMax = std::max<int32_t>(0, healthMax - vocation->getHPGain());
manaMax = std::max<int32_t>(0, manaMax - vocation->getManaGain());
capacity = std::max<int32_t>(0, capacity - vocation->getCapGain());
}
if (oldLevel != level) {
std::ostringstream ss;
ss << "You were downgraded from Level " << oldLevel << " to Level " << level << '.';
sendTextMessage(MESSAGE_EVENT_ADVANCE, ss.str());
}
uint64_t currLevelExp = Player::getExpForLevel(level);
uint64_t nextLevelExp = Player::getExpForLevel(level + 1);
if (nextLevelExp > currLevelExp) {
levelPercent = Player::getPercentLevel(experience - currLevelExp, nextLevelExp - currLevelExp);
} else {
levelPercent = 0;
}
}
std::bitset<6> bitset(blessings);
if (bitset[5]) {
Player* lastHitPlayer;
if (_lastHitCreature) {
lastHitPlayer = _lastHitCreature->getPlayer();
if (!lastHitPlayer) {
Creature* lastHitMaster = _lastHitCreature->getMaster();
if (lastHitMaster) {
lastHitPlayer = lastHitMaster->getPlayer();
}
}
} else {
lastHitPlayer = nullptr;
}
if (lastHitPlayer) {
bitset.reset(5);
blessings = bitset.to_ulong();
} else {
blessings = 32;
}
} else {
blessings = 0;
}
sendStats();
sendSkills();
sendReLoginWindow();
if (getSkull() == SKULL_BLACK) {
health = 40;
mana = 0;
} else {
health = healthMax;
mana = manaMax;
}
auto it = conditions.begin(), end = conditions.end();
while (it != end) {
Condition* condition = *it;
if (condition->isPersistent()) {
it = conditions.erase(it);
condition->endCondition(this);
onEndCondition(condition->getType());
delete condition;
} else {
++it;
}
}
} else {
setLossSkill(true);
auto it = conditions.begin(), end = conditions.end();
while (it != end) {
Condition* condition = *it;
if (condition->isPersistent()) {
it = conditions.erase(it);
condition->endCondition(this);
onEndCondition(condition->getType());
delete condition;
} else {
++it;
}
}
health = healthMax;
g_game.internalTeleport(this, getTemplePosition(), true);
g_game.addCreatureHealth(this);
onThink(EVENT_CREATURE_THINK_INTERVAL);
onIdleStatus();
sendStats();
}
}
You mean compile source as debug? Well yea i dont really know how to print maybe something likeSeems like its original unmodified method. The problem might also lies somewhere in Lua functions that your server is running. Anyway some debugging would be best method to find the mistake.
You can run debug mode and watch variables while dying or put prints there to know what values are there. If you will do that, Id also uggest add prints in int LuaScriptInterface::luaCreatureSetMaxHealth(lua_State* L) to check Lua change max hp script usages in that time.
If you dont want to do the debugging/dont know how/cant compile/whatever. Theres a chance you might find smth in Lua player onDeath function files.
local deathListEnabled = true
local maxDeathRecords = 5
function onDeath(player, corpse, killer, mostDamageKiller, unjustified, mostDamageUnjustified)
local playerId = player:getId()
if nextUseStaminaTime[playerId] ~= nil then
nextUseStaminaTime[playerId] = nil
end
player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You are dead.")
if not deathListEnabled then
return
end
local byPlayer = 0
local killerName
if killer ~= nil then
if killer:isPlayer() then
byPlayer = 1
else
local master = killer:getMaster()
if master and master ~= killer and master:isPlayer() then
killer = master
byPlayer = 1
end
end
killerName = killer:getName()
else
killerName = "field item"
end
local byPlayerMostDamage = 0
local mostDamageKillerName
if mostDamageKiller ~= nil then
if mostDamageKiller:isPlayer() then
byPlayerMostDamage = 1
else
local master = mostDamageKiller:getMaster()
if master and master ~= mostDamageKiller and master:isPlayer() then
mostDamageKiller = master
byPlayerMostDamage = 1
end
end
mostDamageName = mostDamageKiller:getName()
else
mostDamageName = "field item"
end
local playerGuid = player:getGuid()
db.query("INSERT INTO `player_deaths` (`player_id`, `time`, `level`, `killed_by`, `is_player`, `mostdamage_by`, `mostdamage_is_player`, `unjustified`, `mostdamage_unjustified`) VALUES (" .. playerGuid .. ", " .. os.time() .. ", " .. player:getLevel() .. ", " .. db.escapeString(killerName) .. ", " .. byPlayer .. ", " .. db.escapeString(mostDamageName) .. ", " .. byPlayerMostDamage .. ", " .. (unjustified and 1 or 0) .. ", " .. (mostDamageUnjustified and 1 or 0) .. ")")
local resultId = db.storeQuery("SELECT `player_id` FROM `player_deaths` WHERE `player_id` = " .. playerGuid)
local deathRecords = 0
local tmpResultId = resultId
while tmpResultId ~= false do
tmpResultId = result.next(resultId)
deathRecords = deathRecords + 1
end
if resultId ~= false then
result.free(resultId)
end
local limit = deathRecords - maxDeathRecords
if limit > 0 then
db.asyncQuery("DELETE FROM `player_deaths` WHERE `player_id` = " .. playerGuid .. " ORDER BY `time` LIMIT " .. limit)
end
if byPlayer == 1 then
local targetGuild = player:getGuild()
targetGuild = targetGuild and targetGuild:getId() or 0
if targetGuild ~= 0 then
local killerGuild = killer:getGuild()
killerGuild = killerGuild and killerGuild:getId() or 0
if killerGuild ~= 0 and targetGuild ~= killerGuild and isInWar(playerId, killer:getId()) then
local warId = false
resultId = db.storeQuery("SELECT `id` FROM `guild_wars` WHERE `status` = 1 AND ((`guild1` = " .. killerGuild .. " AND `guild2` = " .. targetGuild .. ") OR (`guild1` = " .. targetGuild .. " AND `guild2` = " .. killerGuild .. "))")
if resultId ~= false then
warId = result.getDataInt(resultId, "id")
result.free(resultId)
end
if warId ~= false then
db.asyncQuery("INSERT INTO `guildwar_kills` (`killer`, `target`, `killerguild`, `targetguild`, `time`, `warid`) VALUES (" .. db.escapeString(killerName) .. ", " .. db.escapeString(player:getName()) .. ", " .. killerGuild .. ", " .. targetGuild .. ", " .. os.time() .. ", " .. warId .. ")")
end
end
end
end
end