| 05-07-2009, 05:52 AM | #1 |
I'm using Earth-Fury's SetUnitMaxState system in my map, and under certain conditions it causes the game to crash without an error screen (i.e. poof right to desktop). I did some debugging, and I noticed that the system crashes when the difference between max hp and current hp is greater than ~2.4 million (max hp - current hp). To be more clear, the system crashes when it has to change max hp (in this case decrease it) by more than ~2.4 million. As you can see I am using a sufficiently high max power of 2. What can I do about this? Here is the system code; JASS:////////////////////////////////////////////////////////////////////////////////////////// //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ //@ SetUnitMaxState //@======================================================================================= //@ Credits: //@--------------------------------------------------------------------------------------- //@ Written by: //@ Earth-Fury //@ Based on the work of: //@ Blade.dk //@ //@ If you use this system, please credit all of the people mentioned above in your map. //@======================================================================================= //@ SetUnitMaxState Readme //@--------------------------------------------------------------------------------------- //@ //@ SetUnitMaxState() is a function origionally written by Blade.dk. It takes advantage of //@ a bug which was introduced in one of the patches: Bonus life and mana abilitys will //@ only ever add the bonus ammount for level 1. However, when removed, they will remove //@ the ammount they should have added at their current level. This allows you to change a //@ units maximum life and mana, without adding a perminent ability to the unit. //@ //@--------------------------------------------------------------------------------------- //@ Adding SetUnitMaxState to your map: //@ //@ Simply copy this library in to a trigger which has been converted to custom text. //@ After that, you must copy over the abilitys. This is made easy by the ObjectMerger in //@ JASS NewGen. Distributed with this system are //! external calls to the ObjectMerger. //@ Simply copy both of them in to your map, save your map, close and reopen your map in //@ the editor, and remove the external calls. (Or otherwise disable them. Removing the ! //@ after the // works.) //@ //@--------------------------------------------------------------------------------------- //@ Using SetUnitMaxState: //@ //@ nothing SetUnitMaxState(unit <target>, unitstate <state>, real <new value>) //@ //@ This function changes <target>'s unitstate <state> to be eqal to <new value>. Note //@ that the only valid unitstates this function will use are UNIT_STATE_MAX_MAN and //@ UNIT_STATE_MAX_LIFE. Use SetUnitState() to change other unitstates. //@ //@ nothing AddUnitMaxState(unit <target>, unitstate <state>, real <add value>) //@ //@ This function adds <add value> to <target>'s <state> unitstate. <add value> can be //@ less than 0, making this function reduce the specified unitstate. This function will //@ only work with the unitstates UNIT_STATE_MAX_LIFE and UNIT_STATE_MAX_MANA. //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ////////////////////////////////////////////////////////////////////////////////////////// library SetUnitMaxState initializer Initialize globals //======================================================================================== // Configuration //======================================================================================== // The rawcode of the life ability: private constant integer MAX_STATE_LIFE_ABILITY = 'A03W' // The maximum power of two the abilitys use: private constant integer MAX_STATE_MAX_POWER = 22 endglobals //======================================================================================== // System Code //---------------------------------------------------------------------------------------- // Do not edit below this line unless you wish to change the way the system works. //======================================================================================== globals private integer array PowersOf2 endglobals function SetUnitMaxState takes unit u, unitstate state, real newValue returns nothing local integer stateAbility local integer newVal = R2I(newValue) local integer i = MAX_STATE_MAX_POWER local integer offset if state == UNIT_STATE_MAX_LIFE then set stateAbility = MAX_STATE_LIFE_ABILITY else debug call BJDebugMsg("SetUnitMaxState Error: Invalid unitstate") return endif set newVal = newVal - R2I(GetUnitState(u, state)) if newVal > 0 then set offset = MAX_STATE_MAX_POWER + 3 elseif newVal < 0 then set offset = 2 set newVal = -newVal else return endif loop exitwhen newVal == 0 or i < 0 if newVal >= PowersOf2[i] then call UnitAddAbility(u, stateAbility) call SetUnitAbilityLevel(u, stateAbility, offset + i) call UnitRemoveAbility(u, stateAbility) set newVal = newVal - PowersOf2[i] else set i = i - 1 endif endloop endfunction function AddUnitMaxState takes unit u, unitstate state, real addValue returns nothing call SetUnitMaxState(u, state, GetUnitState(u, state) + addValue) endfunction private function Initialize takes nothing returns nothing local integer i = 1 set PowersOf2[0] = 1 loop set PowersOf2[i] = PowersOf2[i - 1] * 2 set i = i + 1 exitwhen i == MAX_STATE_MAX_POWER + 3 endloop endfunction endlibrary |
| 05-07-2009, 06:28 AM | #2 |
maybe try to add some additional levels to the ability, and increase MAX_STATE_MAX_POWER
2^22 is roughly 4 million ..at the moment so AFAIK that shouldnt be a problem ...should it ?? ah well ...give it a try anyway... |
| 05-07-2009, 08:12 AM | #3 |
I tried to the 26th but no change. I don't think increasing it is the solution. |
| 05-07-2009, 10:39 AM | #4 |
Increasing the max power of 2 only increase efficiency, not the actual systems range. It basically adds (or subtracts) the highest power of 2 the system has that is less-than or equal to the difference between the current value and the desired one, until the difference is gone. (It abuses a bug to do the actual life/mana altering, but I've never read of an ill effect from (ab)using that bug.) The problem may lay in the fact that the amount added by the life ability it too high/low at any one time. (Too high a power of 2.) You did actually modify the life (and/or mana) ability to match the new range set with the MAX_STATE_MAX_POWER variable, right..? (I always meant to write better documentation..) |
| 05-07-2009, 11:23 AM | #5 |
Yes, with MAX_STATE_MAX_POWER == 22 my ability has +/- ~4 million. |
| 05-07-2009, 11:57 AM | #6 |
Just add exceptions* to your system, if difference more then %many% use different function with steps like 2400000 |
| 05-07-2009, 02:37 PM | #7 |
Try to cause the crash with a hardcoded case (ie replace the function argument with a fixed local, then remove the unused if statement branches, then unroll the loop, etc). You should end up with a function with no IFs, no LOOPs, and a really obvious problem. |
| 05-08-2009, 08:49 AM | #8 | |
Quote:
The problem is not obvious to me, would you care to help/elaborate? |
| 05-08-2009, 11:58 AM | #9 |
Well first you need to find a simple case to cause it. These things are always simple in hindsight. I have no idea what it is yet, either. You need to simplify the function while preserving the crash, so you can find out what's causing it. It's bug-finding 101. |
| 05-08-2009, 12:50 PM | #10 |
Crush without error is thread lockup. To improve your chances to get answer post map, with this function cause 100% crush all time. Random errors is nearly impossible to fix. |
| 05-08-2009, 06:55 PM | #11 |
Does this bug occur when testing for the same max health change in a different map, or does it only occur in EleTD? I was trying to find this system to do some tests regarding it, but I couldn't find it anywhere, could someone link me? |
| 05-08-2009, 08:23 PM | #12 |
| 05-10-2009, 10:40 AM | #13 |
A good base case would be this (since it is what I am doing)... Take a unit with 5 million hp, set its health to 50%, make its max life equal to current. Crash? |
| 05-10-2009, 04:42 PM | #14 |
Great, now provide code for that exact test case, and simplify it as much as you can while preserving the crash. |
