alejandro762
Well-Known Member
- Joined
- Sep 6, 2021
- Messages
- 257
- Reaction score
- 73
This monster level works.this working or not???V
Tested versions: 1.4 TFS, Otbr (dont work properly) , Canary: Work ( need to adapt code).
This monster level works.this working or not???V
Simply, add Monster Levels to the monsters that cannot be summoned by a mage, in case, copy paste rat, and the rat that can be summoned will be different, change name or something else, there is a large possibility.hello everyone!
are u good?
let me ask u something,
did u guys noticed something about the summons? i implemented as well you guys talking about and further i noticed the mages when summon a monster get a big kid with levels, maybe it can be cool considering different mechanics but not for a older protocol. any idea about how to solve it?
thanks in advance!
cheers.
uoww, awesome idea i was thinking in something more complex about src code, but thats a easy way to deal with... thanks dude!Simply, add Monster Levels to the monsters that cannot be summoned by a mage, in case, copy paste rat, and the rat that can be summoned will be different, change name or something else, there is a large possibility.
<?xml version="1.0" encoding="UTF-8"?>
<monster name="Troll" nameDescription="a troll" race="blood" experience="20" speed="23" manacost="290">
<health now="50" max="50" />
<level min="0" max="4" />
<look type="15" head="0" body="0" legs="0" feet="0" corpse="3987" />
<targetchange interval="1000" chance="0" />
<targetstrategy nearest="100" weakest="0" mostdamage="0" random="0" />
<flags>
<flag summonable="1" />
<flag attackable="1" />
<flag hostile="1" />
<flag illusionable="1" />
<flag convinceable="1" />
<flag pushable="1" />
<flag canpushitems="0" />
<flag canpushcreatures="0" />
<flag targetdistance="1" />
<flag runonhealth="15" />
</flags>
<attacks attack="10" skill="15">
<attack level="4" name="fire" min="-90" max="-170" range="7" radius="3" target="1" chance="3">
<attribute key="shootEffect" value="fire" />
<attribute key="areaEffect" value="firearea" />
</attack>
</attacks>
<defenses armor="6" defense="8">
</defenses>
<voices>
<voice sentence="Grrrr" />
<voice sentence="Groar" />
<voice sentence="Gruntz!" />
<voice sentence="Hmmm, bugs." />
<voice sentence="Hmmm, dogs." />
</voices>
<loot>
<item id="3031" countmax="10" chance="600" /> <!-- a gold coin -->
<item id="3268" countmax="1" chance="180" /> <!-- a hand axe -->
<item id="3552" countmax="1" chance="100" /> <!-- leather boots -->
<item id="3355" countmax="1" chance="100" /> <!-- a leather helmet -->
<item id="3577" countmax="1" chance="150" /> <!-- meat -->
<item id="3003" countmax="1" chance="80" /> <!-- a rope -->
<item id="3054" countmax="1" chance="1" /> <!-- a silver amulet -->
<item id="3277" countmax="1" chance="200" /> <!-- a spear -->
<item id="3336" countmax="1" chance="50" /> <!-- a studded club -->
<item id="3412" countmax="1" chance="150" /> <!-- a wooden shield -->
</loot>
</monster>
hello everyone!
i got another doubt about this system, i was trying in c++ some implementations for it, but until now without success, the thing is i was trying to implement a way to use the variable level of monster.xml for the attack and loot node inside the file, for example, for a troll.xml a way for the trolls of different levels has different behaviors, attacks and loots and for it just input in .xml of the monster something like this:
XML:<?xml version="1.0" encoding="UTF-8"?> <monster name="Troll" nameDescription="a troll" race="blood" experience="20" speed="23" manacost="290"> <health now="50" max="50" /> <level min="0" max="4" /> <look type="15" head="0" body="0" legs="0" feet="0" corpse="3987" /> <targetchange interval="1000" chance="0" /> <targetstrategy nearest="100" weakest="0" mostdamage="0" random="0" /> <flags> <flag summonable="1" /> <flag attackable="1" /> <flag hostile="1" /> <flag illusionable="1" /> <flag convinceable="1" /> <flag pushable="1" /> <flag canpushitems="0" /> <flag canpushcreatures="0" /> <flag targetdistance="1" /> <flag runonhealth="15" /> </flags> <attacks attack="10" skill="15"> <attack level="4" name="fire" min="-90" max="-170" range="7" radius="3" target="1" chance="3"> <attribute key="shootEffect" value="fire" /> <attribute key="areaEffect" value="firearea" /> </attack> </attacks> <defenses armor="6" defense="8"> </defenses> <voices> <voice sentence="Grrrr" /> <voice sentence="Groar" /> <voice sentence="Gruntz!" /> <voice sentence="Hmmm, bugs." /> <voice sentence="Hmmm, dogs." /> </voices> <loot> <item id="3031" countmax="10" chance="600" /> <!-- a gold coin --> <item id="3268" countmax="1" chance="180" /> <!-- a hand axe --> <item id="3552" countmax="1" chance="100" /> <!-- leather boots --> <item id="3355" countmax="1" chance="100" /> <!-- a leather helmet --> <item id="3577" countmax="1" chance="150" /> <!-- meat --> <item id="3003" countmax="1" chance="80" /> <!-- a rope --> <item id="3054" countmax="1" chance="1" /> <!-- a silver amulet --> <item id="3277" countmax="1" chance="200" /> <!-- a spear --> <item id="3336" countmax="1" chance="50" /> <!-- a studded club --> <item id="3412" countmax="1" chance="150" /> <!-- a wooden shield --> </loot> </monster>
if you take a look in the attacks section in the code above, i tried to declare a level that will give for the troll of that level differents types of attacks, any idea about how to implement it?
with my tests and changes inside monsters.cpp and monster.cpp in the respective funcions "Monsters::loadMonster" and "Monster::Monster(MonsterType* mtype)" was with no success...
thanks in advance!
cheers.
Shouldn't crash, you added the level flag to the monsters? You'll have to add it to each monster, try this with a low amount of monster first, just for testing.I added this system and it causes a server collision
Server Crash
<level min="5" max="100" />
monsterBonusHealth = 0.5
monsterBonusSpeed = 0.02
monsterBonusDamage = 0.02
There is a big error after adding this system. If you talk to any NPC, a crash occurs. If you try to give yourself some levels addskill, a crash occurs.Shouldn't crash, you added the level flag to the monsters? You'll have to add it to each monster, try this with a low amount of monster first, just for testing.
XML:<level min="5" max="100" />
Also remember to add the config.lua lines
LUA:monsterBonusHealth = 0.5 monsterBonusSpeed = 0.02 monsterBonusDamage = 0.02
Here's the whole code if you wish to merge it or cherry pick it
![]()
Monster Levels https://otland.net/threads/tfs-1-3-monster-levels.260470/ · ralke23/Greed-TFS-1.5-Downgrades@7175b79
Including every possible commit, I tried to add skulls for monster aswell based on level but wasn't possible. Co-Authored-By: infernumx <[email protected]>github.com
Yes! That's true, any event that adds experience will crash the server. I didn't remember that, it's been so much time using this system that I just forgot about it. But the bug is there. Anyways, i've been using it for a year or so and never had to use add experience events anymore, it's kinda tricky, becuase I even used this crash to get ensure that no one uses add experience commands anymore on server (otherwise will crash and i'll inmediatly know it).There is a big error after adding this system. If you talk to any NPC, a crash occurs. If you try to give yourself some levels addskill, a crash occurs.
Yes, your system is what I am using now
Post automatically merged:
View attachment 84611
True but you can still use player:addExperience.Yes! That's true, any event that adds experience will crash the server. I didn't remember that, it's been so much time using this system that I just forgot about it. But the bug is there. Anyways, i've been using it for a year or so and never had to use add experience events anymore, it's kinda tricky, becuase I even used this crash to get ensure that no one uses add experience commands anymore on server (otherwise will crash and i'll inmediatly know it).
I will take a look into it to see if I can solve it, since I didn't had the necessity, I just passed from that. If someone wishes to contribute on fixing this is welcome! Regards ^^
True but you can still use player:addExperience.
I add this monster level to a 13.32 so function on a script action on use or a chest wont work , the trick is create an item that you Will change it to an npc for experience , add to npc player:addExperience and I Will work.
Sol each time you want addExperience to a player do it by npc and no errors that the trick I found.
Yes! That's true, any event that adds experience will crash the server. I didn't remember that, it's been so much time using this system that I just forgot about it. But the bug is there. Anyways, i've been using it for a year or so and never had to use add experience events anymore, it's kinda tricky, becuase I even used this crash to get ensure that no one uses add experience commands anymore on server (otherwise will crash and i'll inmediatly know it).
I will take a look into it to see if I can solve it, since I didn't had the necessity, I just passed from that. If someone wishes to contribute on fixing this is welcome! Regards ^^
Thanks a lot Aoki, merged here!
Monster* monster = attacker ? attacker->getMonster() : nullptr;
if (monster && monster->getLevel() > 0) {
float bonusDmg = g_config.getFloat(ConfigManager::MLVL_BONUSDMG) * monster->getLevel();
if (bonusDmg != 0.0) {
if (damage.primary.value < 0) {
damage.primary.value += std::round(damage.primary.value * bonusDmg);
}
if (damage.secondary.value < 0) {
damage.secondary.value += std::round(damage.secondary.value * bonusDmg);
}
}
}
Monster* monster = attacker ? attacker->getMonster() : nullptr;
if (monster && monster->getLevel() > 0 && damage.origin != ORIGIN_NONE) {
float bonusDmg = g_config.getFloat(ConfigManager::MLVL_BONUSDMG) * monster->getLevel();
if (bonusDmg != 0.0) {
if (damage.primary.value < 0) {
damage.primary.value += std::round(damage.primary.value * bonusDmg);
}
if (damage.secondary.value < 0) {
damage.secondary.value += std::round(damage.secondary.value * bonusDmg);
}
}
}
SpectatorVec spectators;
if (targetPlayer && target->hasCondition(CONDITION_MANASHIELD) && damage.primary.type != COMBAT_UNDEFINEDDAMAGE) {
int32_t manaDamage = std::min<int32_t>(targetPlayer->getMana(), healthChange);
if (manaDamage != 0) {
if (damage.origin != ORIGIN_NONE) {
const auto& events = target->getCreatureEvents(CREATURE_EVENT_MANACHANGE);
if (!events.empty()) {
for (CreatureEvent* creatureEvent : events) {
creatureEvent->executeManaChange(target, attacker, damage);
}
healthChange = damage.primary.value + damage.secondary.value;
if (healthChange == 0) {
return true;
}
manaDamage = std::min<int32_t>(targetPlayer->getMana(), healthChange);
damage.origin = ORIGIN_NONE;
}
}
function Monster:onDropLoot(corpse)
local function calculateLevelBonus(healthRatio)
if healthRatio >= 4 then -- Level 3
return function(originalChance)
local bonus = math.floor(originalChance * 0.5)
return math.max(bonus, 2000)
end
elseif healthRatio >= 3 then -- Level 2
return function(originalChance)
local bonus = math.floor(originalChance * 0.25)
return math.max(bonus, 1500)
end
elseif healthRatio >= 2 then -- Level 1
return function(originalChance)
local bonus = math.floor(originalChance * 0.1)
return math.max(bonus, 1000)
end
end
return function(originalChance) return 0 end
end
local maxHealth = self:getMaxHealth()
local baseHealth = self:getType():getHealth()
local healthRatio = maxHealth / baseHealth
local levelBonus = calculateLevelBonus(healthRatio)
print(string.format("Health - Max: %d, Base: %d, Ratio: %.2f", maxHealth, baseHealth, healthRatio))
local addedItems = {}
local monsterType = self:getType()
if monsterType then
local lootList = monsterType:getLoot()
if lootList then
for _, lootData in ipairs(lootList) do
local bonusAmount = levelBonus(lootData.chance)
local finalChance = math.min(lootData.chance + bonusAmount, 85000)
local baseChancePercent = (lootData.chance / 1000)
local bonusPercent = (bonusAmount / 1000)
local finalChancePercent = (finalChance / 1000)
print(string.format("Loot ID: %d | Base Chance: %.2f%% | Bonus: %.2f%% | Final Chance: %.2f%%",
lootData.itemId, baseChancePercent, bonusPercent, finalChancePercent))
if math.random(85000) <= finalChance then
if not addedItems[lootData.itemId] then
corpse:addItem(lootData.itemId, lootData.maxCount or 1)
addedItems[lootData.itemId] = true
end
end
end
end
end
8.6 doesn't need this change right? Already merged the code to see how it goes. So much thanks!in combatChangeHealth, add "damage.origin = ORIGIN_NONE;" below "manaDamage = std::min<int32_t>(targetPlayer->getMana(), healthChange);"
This is to not activate onHealthChange events again if you took damage that broke your manashield.
How should it go if I have a range of, for example, white skulled monsters from level 1 to level 30, red skulled from level 30 to 90 and black from 90 to 9999 for example. I must place if healthRatio < 30 and healthRatio > 1 then, if healthRatio < 90 and healthRatio > 30 then, and so on? Thanks in advance!Extra Loot depending on HP (made for Monster Levels system)
View attachment 89516
(these calculations were made for creatures with max 3 levels and max drop rate of 94%)
~ For normal monsters (level 0), no bonus is applied, base loot rates are set in your creature.xml
~ For level 1 monsters:
Takes 10% from the base drop chance, applies on top of base drop chance.
With a minimum bonus of 1%.
~ For level 2 monsters:
Takes 25% from the base drop chance, applies on top of base drop chance.
With a minimum bonus of 1.5%.
~ For level 3 monsters:
Takes 50% from the base drop chance, applies on top of base drop chance.
With a minimum bonus of 2%.
Notes:
- 85000 sets the maximum % chance an item can drop to prevent insane drops, currently 85%, edit this if you want.
- Rare items with a lower drop chance will always have a flat 1 or 2% extra chance of being dropped.
- This calculates the loot based on the creatures bonus health gained with the Monster Levels system in difference with it's base health.
- This is for 3 extra monster levels where level 0 is the base if you use higher numbers, adjust the script and rates accordingly.
data/creaturescripts/scripts/monster.lua
AboveLUA:function Monster:onDropLoot(corpse)
Add the following:LUA:local function calculateLevelBonus(healthRatio) if healthRatio >= 4 then -- Level 3 return function(originalChance) local bonus = math.floor(originalChance * 0.5) return math.max(bonus, 2000) end elseif healthRatio >= 3 then -- Level 2 return function(originalChance) local bonus = math.floor(originalChance * 0.25) return math.max(bonus, 1500) end elseif healthRatio >= 2 then -- Level 1 return function(originalChance) local bonus = math.floor(originalChance * 0.1) return math.max(bonus, 1000) end end return function(originalChance) return 0 end end
Inside function Monster;onDropLoot(corpse)
Below
LUA:local maxHealth = self:getMaxHealth() local baseHealth = self:getType():getHealth() local healthRatio = maxHealth / baseHealth local levelBonus = calculateLevelBonus(healthRatio) print(string.format("Health - Max: %d, Base: %d, Ratio: %.2f", maxHealth, baseHealth, healthRatio)) local addedItems = {} local monsterType = self:getType() if monsterType then local lootList = monsterType:getLoot() if lootList then for _, lootData in ipairs(lootList) do local bonusAmount = levelBonus(lootData.chance) local finalChance = math.min(lootData.chance + bonusAmount, 85000) local baseChancePercent = (lootData.chance / 1000) local bonusPercent = (bonusAmount / 1000) local finalChancePercent = (finalChance / 1000) print(string.format("Loot ID: %d | Base Chance: %.2f%% | Bonus: %.2f%% | Final Chance: %.2f%%", lootData.itemId, baseChancePercent, bonusPercent, finalChancePercent)) if math.random(85000) <= finalChance then if not addedItems[lootData.itemId] then corpse:addItem(lootData.itemId, lootData.maxCount or 1) addedItems[lootData.itemId] = true end end end end end
Updated~
I wonder if someone managed to do this? Otherwise, there's any AI that could convert canary/otservbr creatures to old syntaxis? Please help me on this one! Regardshow to add it here ?
Compilation works, it show:
You see a wolf, it is level 0.
But can't add monster.minLevel = 5 / monster.maxLevel = 100
or adding it into monster.defenses or something else, minLevel = 5 / maxLevel = 100
doesn't work, anyone know ?
Also tried:
LUA:monster.level = { min = 5, max = 100 }