| 04-22-2009, 09:22 PM | #1 |
Anitarf, I think I may have found a bug ... You know that last optional parameter from the create function? JASS:function ABuffApply takes aBuffType id, unit u, unit caster, real duration, integer level, integer data returns boolean Well, I am using it to save a structure with information about my caster and about a skill he gets. I am now trying to mix UnitProperties (from Litany) with ABuff, to create the ultimate way of making spells, however, to do so, I need to use structs, there is extra data that depends on each caster that I need to save. To do this I created an auxiliary structure called aCaster. As you can see in the next code example, I set it on the Create function. So mainly, the spell should be MUI, however it is not. If 2 units use the spell at the same time, the second unit gets the "new armor bonus + old armor bonus" and it should only get the "new armor bonus". I think it is a bug (you know when users are newbs they usually blame the tool lol) but, in case it is not a bug, what am I doing wrong? Is there a way to fix it? Btw, I want your quick opinion, do you think the coding practice I use is "healthy?" Would you approve such a spell? JASS://=========================================================================== //This ability gives the caster bonus armor depending on the number of //allied ChaosOrc units and Undead units nearby. It gains 1 armor per each unit //and can get a maximum armor bonus of 5. // //Requires: // - Abuff // - UnitProperties // //@author Flame_Phoenix // //@version 1.1 //=========================================================================== scope ChaoticDetermination initializer Init //=========================================================================== //=============================SETUP START=================================== //=========================================================================== globals private constant integer AID = 'A052' private constant integer AURA_ID = 'A03O' private constant integer BUFF_ID = 'B00B' private constant string EFF = "Abilities\\Spells\\NightElf\\Taunt\\TauntCaster.mdl" endglobals private constant function MaxBonus takes integer level returns integer //the maximum amount of armor the caster can receive return 5 endfunction private constant function Radius takes integer level returns real //the AOE of the spell return 300. endfunction private constant function Duration takes integer level returns real //the duration of the spell return 10. endfunction private function CountUnits takes unit caster, unit helper returns boolean //the units that will add the bonus to the caster return IsUnitAlly(helper, GetOwningPlayer(caster)) and (IsUnitType(helper, UNIT_TYPE_STRUCTURE) == false) and (IsUnitType(helper, UNIT_TYPE_MECHANICAL) == false) and (GetWidgetLife(helper) > 0.405) and (caster != helper) and (IsUnitType(helper, UNIT_TYPE_UNDEAD) or (Race[GetPlayerId(GetOwningPlayer(helper))+1] == "Chaos_Orc")) endfunction //=========================================================================== //=============================SETUP END===================================== //=========================================================================== globals private group helpers private boolexpr chooseHelpers private unit tmpCaster public aBuffType id = 0 endglobals private struct aCaster unit caster integer bonus method onDestroy takes nothing returns nothing call BJDebugMsg(I2S(.bonus)) endmethod endstruct //=========================================================================== private function ChooseHelpers takes nothing returns boolean return CountUnits(tmpCaster, GetFilterUnit()) endfunction //=========================================================================== private function Cleanup takes aBuff eventBuff returns nothing local aCaster data = eventBuff.data call UnitModifyArmor(data.caster, -data.bonus) call data.destroy() call UnitRemoveAbility(eventBuff.target.u, AURA_ID) //so we don't wait 2 seconds because of the aura call UnitRemoveAbility(eventBuff.target.u, BUFF_ID) endfunction //=========================================================================== private function Create takes aBuff eventBuff returns nothing local aCaster data = aCaster.create() set data.caster = eventBuff.target.u call DestroyEffect(AddSpecialEffect(EFF, GetUnitX(data.caster), GetUnitY(data.caster))) //here we count the bonus we will add and clear the group set tmpCaster = data.caster call GroupEnumUnitsInRange(helpers, GetUnitX(data.caster), GetUnitY(data.caster), Radius(eventBuff.level), chooseHelpers) set data.bonus = CountUnitsInGroup(helpers) call GroupClear(helpers) //if we have more then 0 units, then we add the ability, else we don't if data.bonus > 0 then //now we add the ability to the caster and set it's level if data.bonus > MaxBonus(eventBuff.level) then set data.bonus = MaxBonus(eventBuff.level) call UnitModifyArmor(data.caster, data.bonus) else call UnitModifyArmor(data.caster, data.bonus) endif endif //now we add the buff, we always add the buff xD call UnitAddAbility(data.caster, AURA_ID) //prevent morphing from removing the ability call UnitMakeAbilityPermanent(data.caster, true, AURA_ID) set eventBuff.data = integer(data) endfunction //=========================================================================== private function Conditions takes nothing returns boolean local integer level local real duration local unit caster if GetSpellAbilityId() == AID then set caster = GetTriggerUnit() set level = GetUnitAbilityLevel(caster, AID) set duration = Duration(level) call ABuffApply(id, caster, caster, duration, level, 0) endif set caster = null return false endfunction //=========================================================================== private function Init takes nothing returns nothing local trigger ChaoticDetermTrg = CreateTrigger( ) call TriggerRegisterAnyUnitEventBJ(ChaoticDetermTrg, EVENT_PLAYER_UNIT_SPELL_EFFECT ) call TriggerAddCondition(ChaoticDetermTrg, Condition(function Conditions)) //setting our globals set helpers = CreateGroup() set chooseHelpers = Condition(function ChooseHelpers) set id = aBuffType.create() //setting Abuff set id.eventCreate = ABuffEvent_Create.Create set id.eventCleanup = ABuffEvent_Cleanup.Cleanup //preloading effects call Preload(EFF) endfunction endscope |
| 04-22-2009, 10:05 PM | #2 |
I don't see any way how the messed up bonuses could be my fault, sorry. All ABuff does is call your functions and debug messages in them should show that they are being called correctly when the buff is created or cleaned up. By the way, you don't need the aCaster struct since you could store the bonus integer to the buff's data field directly. Also, your buff lacks a refresh function which might not be an issue if the duration of the spell is shorter than the cooldown because it's a self-target spell, however if you plan on making this a public spell then that might not always be the case. |
| 04-23-2009, 01:34 PM | #3 | |||
Quote:
It just makes no sense to me, if all your unit, duration and level variables are MUI, why this one is not!?... I will post a replay or a video soon... this beats my brain... Quote:
Quote:
Thx for the quick review. EDIT EDIT EDIT Ok, here is the replay. It is like 20 seconds + 10 seconds of loading screen, it is really short.I hope you understand the problem when seeing the bug because afaik, the code I posted is clean ... =S |
| 04-23-2009, 07:35 PM | #4 |
Your indexing system is probably failing, so the bonuses get stored all at position 0, meaning it adds them all to one |
| 04-23-2009, 07:45 PM | #5 | |
Quote:
Maybe ABuff bugs if caster = target? I made a few more tests. The results are funny, I think that the problem is from Litany's approved system (UnitProperties) and not from Abuff ... but I am really NOT sure ...Here is the code for your joy! JASS://=========================================================================== //This ability gives the caster bonus armor depending on the number of //allied ChaosOrc units and Undead units nearby. It gains 1 armor per each unit //and can get a maximum armor bonus of 5. // //Requires: // - Abuff // - UnitProperties // //@author Flame_Phoenix // //@version 1.1 //=========================================================================== scope ChaoticDetermination initializer Init //=========================================================================== //=============================SETUP START=================================== //=========================================================================== globals private constant integer AID = 'A052' private constant integer AURA_ID = 'A03O' private constant integer BUFF_ID = 'B00B' private constant string EFF = "Abilities\\Spells\\NightElf\\Taunt\\TauntCaster.mdl" endglobals private constant function MaxBonus takes integer level returns integer //the maximum amount of armor the caster can receive return 5 endfunction private constant function Radius takes integer level returns real //the AOE of the spell return 300. endfunction private constant function Duration takes integer level returns real //the duration of the spell return 10. endfunction private function CountUnits takes unit caster, unit helper returns boolean //the units that will add the bonus to the caster return true endfunction //=========================================================================== //=============================SETUP END===================================== //=========================================================================== globals private group helpers private boolexpr chooseHelpers private unit tmpCaster public aBuffType id = 0 endglobals //=========================================================================== private function ChooseHelpers takes nothing returns boolean return CountUnits(tmpCaster, GetFilterUnit()) endfunction //=========================================================================== private function Cleanup takes aBuff eventBuff returns nothing call UnitModifyArmor(eventBuff.target.u, -eventBuff.data) call UnitRemoveAbility(eventBuff.target.u, AURA_ID) //so we don't wait 2 seconds because of the aura call UnitRemoveAbility(eventBuff.target.u, BUFF_ID) endfunction //=========================================================================== private function Create takes aBuff eventBuff returns nothing call DestroyEffect(AddSpecialEffect(EFF, GetUnitX(eventBuff.target.u), GetUnitY(eventBuff.target.u))) call BJDebugMsg("armor= "+I2S(eventBuff.data)) call UnitModifyArmor(eventBuff.target.u, eventBuff.data) //now we add the buff, we always add the buff xD call UnitAddAbility(eventBuff.target.u, AURA_ID) //prevent morphing from removing the ability call UnitMakeAbilityPermanent(eventBuff.target.u, true, AURA_ID) //set eventBuff.data = integer(data) endfunction //=========================================================================== private function Conditions takes nothing returns boolean local integer level local real duration local unit caster if GetSpellAbilityId() == AID then set caster = GetTriggerUnit() set level = GetUnitAbilityLevel(caster, AID) set duration = Duration(level) call ABuffApply(id, caster, caster, duration, level, 2) endif set caster = null return false endfunction //=========================================================================== private function Init takes nothing returns nothing local trigger ChaoticDetermTrg = CreateTrigger( ) call TriggerRegisterAnyUnitEventBJ(ChaoticDetermTrg, EVENT_PLAYER_UNIT_SPELL_EFFECT ) call TriggerAddCondition(ChaoticDetermTrg, Condition(function Conditions)) //setting our globals set helpers = CreateGroup() set chooseHelpers = Condition(function ChooseHelpers) set id = aBuffType.create() //setting Abuff set id.eventCreate = ABuffEvent_Create.Create set id.eventCleanup = ABuffEvent_Cleanup.Cleanup //preloading effects call Preload(EFF) endfunction endscope So basically, the eventBuff.data parameter seems to be correct, for all instances (the BJDebugg message is always "2" which is correct), however my second unit gets +4 armor ... I make no idea why... is this a bug from Litany system or from Abuff? I am sure of one thing, it is not a bug from this small piece of code ... Here is the replay... |
| 04-23-2009, 08:33 PM | #6 |
The indexing system you are using with UnitProperties to store data :o |
| 04-23-2009, 09:02 PM | #7 | |
Quote:
And btw, I don't think Unitproperties indexes units since it just adds abilities to units (not sure though). Ani, do you think this bug (from ABuff or UnitProperties?) should be moved to triggers section? |
| 04-23-2009, 10:59 PM | #8 |
Moved. |
| 04-23-2009, 11:26 PM | #9 |
Neither of them is your problem, you missed the part that you have to call call CreateUnitProperties(YourUnit) before doing anything to a unit via UnitProperties. |
| 04-25-2009, 06:05 PM | #10 | |
Quote:
Anyway, thx for helping! rep++! |
