# Nostalrius 7.7

#### Drinc

##### Active Member
rand()%10 includes the 0, so you get 10 random numbers anyways (0...9), no?...

OTHire is extremely off.
Remember that in RealOTS you can hunt Dragons with Demon Skeletons, you can't do this on OTHire or any other OT because formulas are off, you're only able to do so in Nostalrius and RealOTS itself.

I've received many reports about ranged monsters or something off in the monsters attack, I need video of Tibia 7.7 (RealOTS) showing the monsters shooting spells like Warlock to come up with a solution.
you still wont agree your monsters are incorrect? Did you even play RealOTs?

#### LooSik

##### Active Member
A small code tl;dr.

normal_random(0,10) sample rate 1,000,000
Code:
0 = 13006 1%
1 = 44890 4%
2 = 77615 7%
3 = 115484 11%
4 = 146039 14%
5 = 204712 20%
6 = 146611 14%
7 = 115499 11%
8 = 77941 7%
9 = 44953 4%
10 = 13250 1%
uniform_random(0,10) sample rate 1,000,000
Code:
0 = 90612 9%
1 = 91050 9%
2 = 91115 9%
3 = 90956 9%
4 = 90644 9%
5 = 90975 9%
6 = 90686 9%
7 = 90999 9%
8 = 91099 9%
9 = 90566 9%
10 = 91298 9%
So yeah if any of the monster attack code involved normalized_random, anything that would be for example 3% would be in fact closer to ~0.6%, resulting in possible extremely long delays between attacks.

OP

#### Ezzz

##### Developer
A small code tl;dr.

normal_random(0,10) sample rate 1,000,000
Code:
0 = 13006 1%
1 = 44890 4%
2 = 77615 7%
3 = 115484 11%
4 = 146039 14%
5 = 204712 20%
6 = 146611 14%
7 = 115499 11%
8 = 77941 7%
9 = 44953 4%
10 = 13250 1%
uniform_random(0,10) sample rate 1,000,000
Code:
0 = 90612 9%
1 = 91050 9%
2 = 91115 9%
3 = 90956 9%
4 = 90644 9%
5 = 90975 9%
6 = 90686 9%
7 = 90999 9%
8 = 91099 9%
9 = 90566 9%
10 = 91298 9%
So yeah if any of the monster attack code involved normalized_random, anything that would be for example 3% would be in fact closer to ~0.6%, resulting in possible extremely long delays between attacks.
Do we consider uniform_random the solution for the issue related to attack chance? If so, let me know to push the bug fix.

#### LooSik

##### Active Member
Do we consider uniform_random the solution for the issue related to attack chance? If so, let me know to push the bug fix.
Yeah uniform random is very simillar in behaviour to rand(), just more convinent to use. And decompiled binary of Cip's files is using normal rand for spell attack chance.
Code:
if ( !(rand() % spellData->Delay) && (this->Master ||
TSkill::Get(this->tNonPlayer.tCreature.tSkillBase.Skills[HP]) > *(&unk_81C479C + 84 * this->baseclass_0.baseclass_0.Race) // runaway health
|| random(1, 3) == 1) )
I am not sure if there is anything actually using normalized, would have to dig around, been a while since I've looked into these.

But yeah, with normal_rand looking for 0 to proc. It made any spell in your distro do attack roughly 3-4 times less frequent.

Also you should also perhaps change the 1/3 chance to attack on flee to uniform version as well. As that's also making it way less frequent for additional chance to attack during flee.
Code:
normalized_random(1, 3)
1 = 135932 13%
2 = 728048 72%
3 = 136020 13%
and random(int, int) is just a regular rand() with option to min - max
Code:
int __cdecl random(int a3, int a4)
{
signed int v4; // [email protected]
int result; // [email protected]

v4 = a4 - a3 + 1;
result = a3;
if ( v4 > 0 )
result = rand() % v4 + a3;
return result;
}
So hypothetically if an monster had chance 3. Which should be in fact 25% roughly.
Your monster had around 6% chance to attack with that spell. If it was fleeing, then that chance would be 0.78%.
What should look more like: 25% to attack & when fleeing 8,25%.

Last edited:
OP

#### Ezzz

##### Developer
Yeah uniform random is very simillar in behaviour to rand(), just more convinent to use. And decompiled binary of Cip's files is using normal rand for spell attack chance.
Code:
if ( !(rand() % spellData->Delay) && (this->Master ||
TSkill::Get(this->tNonPlayer.tCreature.tSkillBase.Skills[HP]) > *(&unk_81C479C + 84 * this->baseclass_0.baseclass_0.Race) // runaway health
|| random(1, 3) == 1) )
I am not sure if there is anything actually using normalized, would have to dig around, been a while since I've looked into these.

But yeah, with normal_rand looking for 0 to proc. It made any spell in your distro do attack roughly 3-4 times less frequent.

Also you should also perhaps change the 1/3 chance to attack on flee to uniform version as well. As that's also making it way less frequent for additional chance to attack during flee.
Code:
normalized_random(1, 3)
1 = 135932 13%
2 = 728048 72%
3 = 136020 13%
and random(int, int) is just a regular rand() with option to min - max
Code:
int __cdecl random(int a3, int a4)
{
signed int v4; // [email protected]
int result; // [email protected]

v4 = a4 - a3 + 1;
result = a3;
if ( v4 > 0 )
result = rand() % v4 + a3;
return result;
}
So hypothetically if an monster had chance 3. Which should be in fact 25% roughly.
Your monster had around 6% chance to attack with that spell. If it was fleeing, then that chance would be 0.78%.
What should look more like: 25% to attack & when fleeing 8,25%.
Perfect, thank you for your contribution and maybe with your explanation as to why it wasn't working accurately people start to realize about the server's potential and stop being so hateful, although they hate the server, they are still going to be using it in the end so it's a matter of time of addressing the small issues I have left.

#### emil92b

##### Active Member
can you guys test if a demon enter a fire field, stops attacking?

they also seem to stop attack if you take their health down abit

might be the latest idle fix?

Last edited:
OP

#### Ezzz

##### Developer
can you guys test if a demon enter a fire field, stops attacking?

they also seem to stop attack if you take their health down abit

might be the latest idle fix?
Reproduced, and a bug fix is on it's way.
Edit: Should be fixed along with TFS bug of invisible creatures never going idle, also a bug fix for Gamemasters and invisible creatures.

Last edited:
OP

#### Ezzz

##### Developer
Important changes were pushed, and many invalid issues were closed, please, do not report issues that are not reproducible on last Nostalrius.

Last edited:

Last edited:

#### pink_panther

##### Well-Known Member
Perfect, thank you for your contribution and maybe with your explanation as to why it wasn't working accurately people start to realize about the server's potential and stop being so hateful, although they hate the server, they are still going to be using it in the end so it's a matter of time of addressing the small issues I have left.
Should the monsters spell have an exhaust cool down though?

How often does this onAttacking function tick?

Aren't spell cooldowns 2 seconds? Monsters might be using spells more often now, but maybe the cooldown is off?

OP

#### Ezzz

##### Developer
I'm testing the last commits, first issue I encountered is that player summons don't move now.
Maybe a collateral damage of this commit: Monster Idle Bug fix · TwistedScorpio/[email protected]
or this one: Important bug fixes · TwistedScorpio/[email protected]
It has been fixed, oops

Should the monsters spell have an exhaust cool down though?

How often does this onAttacking function tick?

Aren't spell cooldowns 2 seconds? Monsters might be using spells more often now, but maybe the cooldown is off?
It should be around 1 to 2 seconds tick as far as I'm aware.

#### emil92b

##### Active Member
doesn't that also depend on where the target is located to the monster?

OP

#### Ezzz

##### Developer
doesn't that also depend on where the target is located to the monster?
Never, although RealOTS is known to also have every monster to sometimes double attack.

#### pink_panther

##### Well-Known Member
It should be around 1 to 2 seconds tick as far as I'm aware.
Looks like it's 1 second for all. Were monsters able to have a 1s global cooldown?

1s for instant spells though? so they don't get 2 second cooldown, just runes?

#### pinata

##### Member
Looks like it's 1 second for all. Were monsters able to have a 1s global cooldown?

1s for instant spells though? so they don't get 2 second cooldown, just runes?
You could try moving the for loop in Monster::doAttacking like this:
Code:
if (OTSYS_TIME() >= earliestAttackTime) {
if(!isFleeing())
{
updateLook = true;
if (Combat::closeAttack(this, attackedCreature, FIGHTMODE_BALANCED)) {
egibleToDance = true;
earliestAttackTime = OTSYS_TIME() + 2000;
removeCondition(CONDITION_AGGRESSIVE, true);
}
}
for (spellBlock_t& spellBlock : mType->info.attackSpells) {
if (spellBlock.range != 0 && std::max<uint32_t>(Position::getDistanceX(myPos, targetPos), Position::getDistanceY(myPos, targetPos)) <= spellBlock.range) {
if (uniform_random(1, spellBlock.chance) == 1 && (master || health > mType->info.runAwayHealth || uniform_random(1, 3) == 1)) {
updateLookDirection();

minCombatValue = spellBlock.minCombatValue;
maxCombatValue = spellBlock.maxCombatValue;

spellBlock.spell->castSpell(this, attackedCreature);
egibleToDance = true;
earliestAttackTime = OTSYS_TIME() + 2000;
}
}
}
}
edit:Added earliestAttackTime = OTSYS_TIME() + 2000; when a spell is successfully used. Watching a demon tibiacam, it does seem like the spells and melee attacks happen in the same interval.

Last edited:

#### pink_panther

##### Well-Known Member
Have you tested it since?

#### pinata

##### Member
Have you tested it since?
I just implemented it. It looks very similar to what I saw in the video. I also looked at what OTHire has for that function. It seems there's a variable spell interval that is different based on:

Code:
If the creature is fleeing: 1 sec
else
If the target is in melee range: 2 seconds
else (the target is out of melee range)
If the creature has no path to the target: 1 sec
else If the creature is "melee" type (target distance is <=1): 4 seconds
else
(the creature is "ranged" type): 1 sec
The 2 seconds for melee range makes sense because the video I watched was with a blocker. The other cases would need to be confirmed, and maybe the defensive spell interval needs to be looked into.

Last edit before I pass out:
At around 21:07 here, the Demon switches targets and goes out of melee range and seems to go insane. That might contradict the 4 second time there, but maybe they got that from some other monster? Maybe CIP has a different method of doing the interval? I dunno, but I think your suspicion that the interval is off is correct.

Last edited:

#### Peonso

##### Godly Member
Code:
If the creature is fleeing: 1 sec
else
If the target is in melee range: 2 seconds
else (the target is out of melee range)
If the creature has no path to the target: 1 sec
else If the creature is "melee" type (target distance is <=1): 4 seconds
else
(the creature is "ranged" type): 1 sec
I got those values after dozen hours of tests on real tibia live servers (from @e.e and @Kungenn). e.e even helped setup custom monsters with 100 cast chance. Also some annihilator tibia cams helped to figure out weird stuff (like how monsters spam spells when traped at not ideal range, as demons in annihilator, or any stuff from the other side of a river with no path available). The 4 seconds value I was not sure though, and might be something in the range of 3 to 5 seconds. You guys that have more experience with the 7.7 decompiled code might get the acurate values now that you know what to look for.

I'm amazed how a "perfect replica" totally ignored that aspect and garbage OTHire is being used as resource to fix all those broken features. I would actually advise against that though, it's better to test in the real thing, maybe check OTHire for ideas, but some implementations are estimatives and the code is poorly implemented (because I sux, sorry).

Regarding the video, I would guess it was some weird interaction of fast changing target and changing range. I tested with dragons/hunters for hours and never saw something like that.

Last edited:

#### Felipe93

##### Ghost Member
would mind you
I got those values after dozen hours of tests on real tibia live servers (from @e.e and @Kungenn). e.e even helped setup custom monsters with 100 cast chance. Also some annihilator tibia cams helped to figure out weird stuff (like how monsters spam spells when traped at not ideal range, as demons in annihilator, or any stuff from the other side of a river with no path available). The 4 seconds value I was not sure though, and might be something in the range of 3 to 5 seconds. I guys that have more experience with the decompiled code might get the acurate values now that you know what to look for.

I'm amazed how a "perfect replica" totally ignored that aspect and garbage OTHire is being used as resource to fix all those broken features.

Regarding the video, I would guess it was some weird interaction of fast changing target and changing range. I tested with dragons/hunters for hours and never saw something like that.
it's obvious that othire has more accurate formulas, would you mind to share those codes? i want to add them into otx i mean source code would you give me the link to the commits please'?
@Peonso