Closed heyitsbench closed 1 week ago
To allow things like a halved XP rate or counteracting a double XP weekend, for instance.
There is already a module that doubles the experience on weekends. Reducing it by half is debatable. But anyway, I don't know if it would be better to do it in another module. This one the way it is, I think it works fine. Although you can do validations and variables, but I wouldn't really modify it.
There is already a module that doubles the experience on weekends.
At the time I made this suggestion, I was using that module, and I was trying to use this module to half the doubled XP from that module. I was unaware that I could achieve that with weekendxp rate 1
.
Reducing it by half is debatable. But anyway, I don't know if it would be better to do it in another module. This one the way it is, I think it works fine. Although you can do validations and variables, but I wouldn't really modify it.
I also think it works well currently, but I see no reason why allowing floats as XP rates should be done through an entirely separate module.
There is already a module that doubles the experience on weekends.
At the time I made this suggestion, I was using that module, and I was trying to use this module to half the doubled XP from that module. I was unaware that I could achieve that with
weekendxp rate 1
.Reducing it by half is debatable. But anyway, I don't know if it would be better to do it in another module. This one the way it is, I think it works fine. Although you can do validations and variables, but I wouldn't really modify it.
I also think it works well currently, but I see no reason why allowing floats as XP rates should be done through an entirely separate module.
He may be right. It will be a matter of updating it then. Now I am waiting for some changes to be uploaded, related to translations and then we could try to look at these issues.
Instead of ending up with, say, 1 or 2 experiences, is the idea that it could be a 1.5 experience? If so, then it's probably fine, however, it depends on how you set up the module file. In the module, I would have integer values, and then, I would allow in any case, that the player can choose intermediate values.
Instead of ending up with, say, 1 or 2 experiences, is the idea that it could be a 1.5 experience? If so, then it's probably fine,
Pretty much. Afaik, it only allows whole numbers (e.g. 1, 2, 3, 4...), this suggestion proposes any manner of in-between decimal values be allowed as well (e.g. 0.1, 0.2, 0.5, 1, 1.5...).
Pretty much. Afaik, it only allows whole numbers (e.g. 1, 2, 3, 4...), this suggestion proposes any manner of in-between decimal values be allowed as well (e.g. 0.1, 0.2, 0.5, 1, 1.5...).
Perfect, I'll see what I can do once I finish testing on the current PR.
I rewrote the entire module again, adding decimal values, both in the database and within the code, and yet never multiplied the experience by said values. What's more, no matter how much value I put on it, it was saved in the database when I exited the game, but then it always multiplied it by 1. Reviewing the emulator code, it seems that the amount is always a uint32, so which unfortunately is not enough to modify this module. It would be necessary to see if changes can be made within the emulator and I doubt they will really let us. I don't know if a hook is enough, it seems to me that it is actually a little more complex. GiveXP accepts integer values, and therefore, it seems to me that it prevents the use of decimals. But hey, at least I tried. Maybe, the client also, in some opcode or something, is expecting an integer value, I don't know...
@pangolp
but then it always multiplied it by 1
For me it sounds like a casting error. When looking into the code in this line:
Something like
amount = static_cast<uint32>(static_cast<float>(amount) * data->XPRate);
should be possible. Note that you will have to cast it, otherwise you will get truncation errors.
However I am not sure if the value in the database can be float data->XPRate
. If not this is however also easily fixable, simply specify it as int like it is currently, but as multiple of 1000. Like for example 2500 for 2.5 rate.
This would then work:
amount = (amount * data->XPRate) / 1000;
@pangolp
but then it always multiplied it by 1
For me it sounds like a casting error. When looking into the code in this line:
Something like
amount = static_cast<uint32>(static_cast<float>(amount) * data->XPRate);
should be possible. Note that you will have to cast it, otherwise you will get truncation errors.
However I am not sure if the value in the database can be float
data->XPRate
. If not this is however also easily fixable, simply specify it as int like it is currently, but as multiple of 1000. Like for example 2500 for 2.5 rate.This would then work:
amount = (amount * data->XPRate) / 1000;
It could work yes, the problem is that the emulator, the method, works with a uint32 if I remember correctly or uint8, now I don't remember correctly, I would have to look for it, that's why I think that even if we change things in the module, anyway, eliminate decimals, and round to the nearest integer.
// Called when a player gains XP (before anything is given)
virtual void OnGiveXP(Player* /*player*/, uint32& /*amount*/, Unit* /*victim*/, uint8 /*xpSource*/) { }
void Player::GiveXP(uint32 xp, Unit* victim, float group_rate, bool isLFGReward)
But it would be a matter of investigating and testing. At the time, I couldn't do it.
After the last pull request I made is merged, I will try to revisit this issue. If the mathematical formula discussed here works, and there are no modifications to be made to the emulator, I see no reason not to make the change.
I would also like to set a timer, as I have done in other modules, so that it has to wait a while and does not execute commands constantly. Avoiding unnecessary queries. Although perhaps, here, it is not so useful, but in other modules, where queries are made to the database, it is good to set a timer.
I managed to get a result, thanks to the account proposed in this issue, that is quite similar to what they want to do, although if the x1 experience was 56, the emulator would always give you 5, because it has no way to do it otherwise. Also, the client reflects decimal values, I think. So changes would have to be made to the client as well. I think it is quite similar. It is not perfect, but pretty close. I don't know what you think.
.xp set 1
= 50 (Although I also got 56 sometimes.)
.xp set 0.1
(5. Although it seems to be round, it is not always, in this case it is, because x1 is 50.)
although if the x1 experience was 56, the emulator would always give you 5, because it has no way to do it otherwise
That is because if you cast it to uint (like in my solution above), it will always truncate the value after the comma and as such round down.
If you want to fix that (but I do not think thats important) you can use std::round:
// include it at top
#include <cmath>
amount = static_cast<uint32>(std::round(static_cast<float>(amount) * data->XPRate));
although if the x1 experience was 56, the emulator would always give you 5, because it has no way to do it otherwise
That is because if you cast it to uint (like in my solution above), it will always truncate the value after the comma and as such round down.
If you want to fix that (but I do not think thats important) you can use std::round:
// include it at top #include <cmath> amount = static_cast<uint32>(std::round(static_cast<float>(amount) * data->XPRate));
I'm going to try it. Thank you. And if it doesn't work, for emulator/client issues. At least, it's pretty close and it's a new challenge and functionality for the module. Because the customer, at least in the experience bar, seems to reflect whole values. And the player's experience table, not if it's whole or allows the use of intermediate values (I guess not).
To allow things like a halved XP rate or counteracting a double XP weekend, for instance.