How often a monster cast spells depends on many factors. I'm not really sure how it's coded in Nostalrius, if a chance of 3 is taken by the code as 25%, it's off, it should be 33.3%. I handled that issue with OTHire, and reseached on the stolen files servers, where I could edit monsters and set the conditions. Code is probably lame, but it works. There is some guess work, marginal though.I’ve been curious about some of the previous discussion on how often monsters cast spells etc, so I’ve done a little bit of observation/research and thought I’d share what I’ve learned so far.
TL;DR:
- As pinata suggested, I think spell chance should be calculated using uniform_random(1, spellBlock.chance) == 1.
- I also think spell chance should be calculated every other second. From what I can tell, it’s every second in Nostalrius.
- The game time doesn’t seem to be running accurately, e.g. duration of spells like utevo lux is incorrect and inconsistent.
Reasoning / theory / long version:
It seems to me that melee and spells shouldn’t be thought of as separate events, which they seem to be in Nostalrius(?). From the clips LooSik shared, it seems that an attack cycle happens every 2000 ms and that both melee and spells happen at the same time. And that some circumstances can cause this interval to be only 1000ms, e.g. no path to target. But in these cases the target is not within melee range, so there’s no actual melee attack. Except for when a creature closes the gap and gets an extra attack cycle, then both melee and spells are used at the same time as shown by LooSik. So it seems that disregarding the exceptions, the spell chance is calculated every 2000 ms, which it’s not in Nostalrius, I’ll get back to that in a bit..
1: I’ve been watching some tibicam clips of demon hunts and taking note of how long the players are being targeted by the demons and how many GFBs are fired in that time. I chose demons because they have a low spell chance of 3 for GFBs, which is easier to measure, and they don’t run, which seem to add some exceptions as we’ve seen with e.g. Warlocks. If the uniform_random thing should be 0, there would be a 1 in 4 chance (0,1,2,3) of the demons firing a GFB and if it should be 1, the chance would be 1 in 3 (1,2,3)
From watching 581 seconds of demons targeting players, I counted 108 GFBs fired. 581 s / 2 s gives 290,5 attack cycles. Divide that by 3 (1,2,3) for the spell chance and you get an expected average of ~96,83 GFBs. Number of counted / expected = 108 / 96,83 ≈ 1,12, so off by 12%. If we instead divide 290,5 by 4 (0,1,2,3) we get 72,625 expected GFBs. 108 / 72,625 ≈ 1,48, so off by 48% .
Even though I think being off by 12% is a bit much to be within error margin, it’s much closer than 48%. And it’s not a huge sample size, several clips etc, but I still thinks it supports the theory. Perhaps someone with the original CIP files can run a similar test to see if the margin of error is smaller under more controlled circumstances and perhaps for a longer period of time? I’d do it myself, but i haven’t been able to get the CIP files to run yet.
2: Now, back to the attack cycle. In Nostalrius, if you set spell chance to 100%, monsters attack every second as opposed to every other second as we’ve seen from the CIP files. From what I can tell, the spellBlock line is called in monster.cpp -> doAttacking. This in turn is called from creature.cpp -> onAttacking, which is called from game.cpp with an interval parameter set to EVENT_CREATURE_THINK_INTERVAL that is set to 1000 in creature.h. Chaning this EVENT_CREATURE_THINK_INTERVAL to 2000, using 1 in the spellBlock chance and setting a demons GFB chance to 1 makes it fire GFBs every other second instead of every second. This suggests that changing demon GFB chance back to 3 with these settings should result in the correct behaviour. But I’m in a bit over my head with the coding here, and EVENT_CREATURE_THINK_INTERVAL is used in other places as well. So changing it has unintended consequences. One thing I’ve noticed already is that monsters turn into corpses slower (2s instead of 1s). I would really appreciate some input on this and alternative ways of solving this. I tried just calling onAttacking(2000) from game.cpp instead of onAttacking(EVENT_CREATURE_THINK_INTERVAL), but that didn’t work for me. They still fired every second.
3: This is a bit unrelated, but I felt that utevo lux didn’t last me as long as I remembered that it should. I looked in the light.lua and found it should last 6 minutes and 10 seconds. I also watched some tibicams and timed their utevo lux to verify this and it seemed to be correct down to the second. But when I used utevo lux in Nostalrius and timed it, it was as I suspected, shorter. I got only 3m20s of light, or 200s as opposed to 370. 370/200 = 1.85 —> 85% off. What’s stranger still is that I’ve done this test many times now, on the same and on different machines and VMs and gotten very different results. On the same day, same setup only a few hours earlier, it was only 30% off. Does anyone have any suggestions on what could cause this? It makes no sense at all to me.
I’ll keep looking into this, but I'd really appreciate any feedback / cooperation / discussion. I really want to help improve this distribution, since I think it’s overall pretty great! Thanks for reading if you got this far!
How often a monster cast spells depends on many factors. I'm not really sure how it's coded in Nostalrius, if a chance of 3 is taken by the code as 25%, it's off, it should be 33.3%. I handled that issue with OTHire, and reseached on the stolen files servers, where I could edit monsters and set the conditions. Code is probably lame, but it works. There is some guess work, marginal though.
What do you mean by a monster being kitted?
You decrease the expected chance of spell being cast to half when monster is in melee range (e.g. dragon is expected 1/14th chance instead of 1/7th). On average this is true, but one of my points is that it should actually be calculated with a 1/7th chance every 2 seconds instead of a 1/14th chance every second. The reason for this is that we've seen in the CIP files that if we set a dragons chance to GFB to 1 (100%), it will do so exactly every other second, not just on average every other second. But since we also see fleeing monsters firing every second under special circumstances, it seems that the interval with which the spell chance is calculated is also a variable, which can be either 1 or 2 sec.
Thoughts on this?
Not always. Monsters fleeing cast spells ~1/3 less often while keeping the 1 second interval.
Yes, this is very clear from your results.From what I figured out the behavior also differs if the monster is melee or ranged. While at melee range interval is 2 seconds, but while at range, ranged monsters cast at 1 second interval
Yes, they're calculated independently, but at the same time. Meaning the cast chance for all spells is calculated in the same code block, independently from each other, and this code block is called with different intervals (1 or 2 sec) depending on the circumstance / creature type.And each spell is independent.
Ah, of course. Those results had me a bit puzzled:Running from it non stop, without letting it get close.
So to sum up:
Ranged creatures: Normally 1 sec interval
Melee creatures: Normally 2 sec interval
No path to target (trapped): 1 sec interval for melee creatures as well
fleeing decreases spell chance to 1/3 of normal, but keeps the same 1 or 2 sec interval depending on creature type
Kitting/chasing decreases spell chance to 3/4 of normal, but keeps the same 1 or 2 sec interval depending on creature type.
They are inconsistent, but the math you made make no-sense. The expected value come from I thinking they should cast at 1 second interval on those situations, which proved to be wrong. But as you can see, hunter got way more closer from the expected value. Those were the first tests, after I started editing monsters and trying other sort of stuff, mostly working with 100% chances to cast spells, I just didn't recorded the data.Ah, of course. Those results had me a bit puzzled:
Dragon kitted never at melee range, expected number of GFB in 10 minutes (1/7 chance) 85 to 86, got 31 to 35.
Hunter kitted never at melee range, expected number of Arrows in 5 minutes (1/2 chance) 150, got 115.
At first I thought they were inconsistent, since 33 / 86 ≈ 0,38 and 115 / 150 ≈ 0,77, but if you assume that the dragon is on a 2 sec interval when kitted, which is consistent with the clips by Loosik of a dragon at 100% chance, then the expected number of GFBs should be the same as when in melee range, i.e. 42-43. and 33 / 43 ≈ 0,77.
Yes, I'll try again to get the real 7.7 up and running to do some more tests.So you still have space to figure out more stuff from #1 and #5, having a real 7.7 and editing stuff might help you. I relied on help from others that had the 7.7 server up and edited monsters for me, but reaching them was always troublesome and I couldn't edit stuff and test as fast as I had ideas.
What part of the math makes no sense?They are inconsistent, but the math you made make no-sense. The expected value come from I thinking they should cast at 1 second interval on those situations, which proved to be wrong. But as you can see, hunter got way more closer from the expected value. Those were the first tests, after I started editing monsters and trying other sort of stuff, mostly working with 100% chances to cast spells, I just didn't recorded the data.
Reading again I got what u saying, as if on those circustances chance to cast a spell is x0,77 while melee monster interval being 2s. Yeah, maybe it's that.What part of the math makes no sense?
I understand that your expected value comes from thinking it should cast every second. What I'm saying is for the hunter that's true, but for the dragon it should calculate its chance of casting every other second instead, since it's a melee creature. That's why I adjusted the expected value to half.
Install libs
What is that about? Someone know?
I already have installed the libs:Install libs
seem to be related to this Container::queryMaxCount() failing in special cases. · Issue #1561 · otland/forgottenserver (https://github.com/otland/forgottenserver/issues/1561)@Manigold im compilling here to test a modification
TypeID = 593
Name = "a loose stone pile"
Flags = {Bank,UseEvent,Unmove,Avoid}
Attributes = {Waypoints=160}
TypeID = 593
Name = "a loose stone pile"
Flags = {Bank,CollisionEvent}
Attributes = {Waypoints=160}
found a bug where fire field is not recognized as a field when its on a pile of stones, for example Orc Fortress entrance, its a pile of stones that you have to dig out with your shovel, but theres a fire field on it and runes doesnt recognize it as a field.
Solution for that:
Go to Data>Items>Items.srv
Find this
Lua:TypeID = 593 Name = "a loose stone pile" Flags = {Bank,UseEvent,Unmove,Avoid} Attributes = {Waypoints=160}
and replace it with this:
Lua:TypeID = 593 Name = "a loose stone pile" Flags = {Bank,CollisionEvent} Attributes = {Waypoints=160}
Nothing serious but little things like that are important if someone is trying to make real tibia based server.