| 06-28-2006, 05:18 AM | #1 |
Ok, probably not that, but there is something wrong. This is my trigger JASS:function SplitHero_SplitsExpired takes nothing returns nothing local timer t = GetExpiredTimer() local unit Caster = GetHandleUnit(GetTriggeringTrigger(),"Caster") local unit Body = GetHandleUnit(Caster,"Body") local unit Mind = GetHandleUnit(Caster,"Mind") local integer BonusAgi = 0 local integer BonusStr = 0 local integer BonusInt = 0 call BJDebugMsg("SplitHero_SplitsExpired initiated") set BonusAgi = GetHandleInt(GetTriggeringTrigger(),"BonusAgi") set BonusStr = GetHandleInt(GetTriggeringTrigger(),"BonusStr") set BonusInt = GetHandleInt(GetTriggeringTrigger(),"BonusInt") call SetHeroAgi(Caster,GetHeroAgi(Caster,false)+BonusAgi,true) call SetHeroStr(Caster,GetHeroStr(Caster,false)+BonusStr,true) call SetHeroInt(Caster,GetHeroInt(Caster,false)+BonusInt,true) call ShowUnitShow(Caster) // call DestroyTrigger(GetTriggeringTrigger()) endfunction function SplitHero_SplitKillCond takes nothing returns boolean local unit Body = GetHandleUnit(GetTriggeringTrigger(),"Body") local unit Mind = GetHandleUnit(GetTriggeringTrigger(),"Mind") call BJDebugMsg("GetKillingUnit: "+GetUnitName(GetKillingUnit())) if ( ( GetKillingUnitBJ() == Body ) ) then call BJDebugMsg("Yay!") return true endif if ( ( GetKillingUnitBJ() == Mind ) ) then call BJDebugMsg("Yay!") return true endif return false endfunction function SplitHero_SplitKill takes nothing returns nothing local trigger t = GetHandleTrigger(GetTriggeringTrigger(),"SplitExpirationTimer") local unit Caster = GetHandleUnit(GetTriggeringTrigger(),"Caster") local unit Body = GetHandleUnit(Caster,"Body") local unit Mind = GetHandleUnit(Caster,"Mind") local integer BonusAgi = 0 local integer BonusStr = 0 local integer BonusInt = 0 call BJDebugMsg("SplitHero_SplitKill initiated") set BonusAgi = GetHandleInt(t,"BonusAgi") set BonusStr = GetHandleInt(t,"BonusStr") set BonusInt = GetHandleInt(t,"BonusInt") if(GetKillingUnit() == Body) then set BonusAgi = BonusAgi + 1 set BonusStr = BonusStr + 2 elseif(GetKillingUnit() == Mind) then set BonusAgi = BonusAgi + 1 set BonusInt = BonusInt + 2 endif call BJDebugMsg("GetKillingUnit: "+GetUnitName(GetKillingUnit())) call BJDebugMsg("BonusStr: "+I2S(BonusStr)) call BJDebugMsg("BonusAgi: "+I2S(BonusAgi)) call BJDebugMsg("BonusInt: "+I2S(BonusInt)) call SetHandleInt(t,"BonusAgi",BonusAgi) call SetHandleInt(t,"BonusStr",BonusStr) call SetHandleInt(t,"BonusInt",BonusInt) // call SetHandleHandle(GetTriggeringTrigger(),"Caster",null) // call SetHandleHandle(GetTriggeringTrigger(),"Body",null) // call SetHandleHandle(GetTriggeringTrigger(),"Mind",null) // call DestroyTrigger(GetTriggeringTrigger()) endfunction function SplitHero_StoreData takes nothing returns nothing local trigger SplitKillTrigger = CreateTrigger() local trigger SplitExpirationTrigger = CreateTrigger() local trigger t2 = CreateTrigger() local timer SplitExpirationTimer = CreateTimer() local unit Caster = GetTriggerUnit() local player p = GetOwningPlayer(Caster) local location CasterLoc= GetUnitLoc(Caster) local unit Body = CreateUnitAtLoc(p,'o003',OffsetLocation(CasterLoc, 128.00, 0),GetUnitFacing(Caster)) local unit Mind = CreateUnitAtLoc(p,'o002',OffsetLocation(CasterLoc, -128.00, 0),GetUnitFacing(Caster)) call ShowUnitHide(Caster) call SetHandleHandle(SplitKillTrigger,"Caster",Caster) call SetHandleHandle(SplitExpirationTrigger,"Caster",Caster) call SetHandleHandle(Caster,"Body",Body) call SetHandleHandle(Caster,"Mind",Mind) call SetHandleHandle(SplitKillTrigger,"SplitExpirationTimer",SplitExpirationTrigger) call UnitApplyTimedLife(Body, 'Bspl', 30.00) call UnitApplyTimedLife(Mind, 'Bspl', 30.00) // call TimerStart(SplitExpirationTimer, 60.00 ,false, null) call TriggerRegisterAnyUnitEventBJ( SplitKillTrigger, EVENT_PLAYER_UNIT_DEATH ) call TriggerAddCondition( SplitKillTrigger, Condition( function SplitHero_SplitKillCond ) ) call TriggerAddAction( SplitKillTrigger, function SplitHero_SplitKill ) call BJDebugMsg("SplitKillTrigger registered") call TriggerRegisterTimerExpireEvent( SplitExpirationTrigger, SplitExpirationTimer ) call TriggerAddAction( SplitExpirationTrigger, function SplitHero_SplitsExpired ) call BJDebugMsg("SplitExpirationTrigger registered") call SetHandleHandle(GetTriggeringTrigger(),"Caster",null) call RemoveLocation(CasterLoc) endfunction //=========================================================================== function Trig_StoreSplitHeroData_Conditions takes nothing returns boolean return not(GetSpellAbilityId() != 'A003') endfunction function Trig_StoreSplitHeroData_Actions takes nothing returns nothing call SplitHero_StoreData() endfunction //=========================================================================== function InitTrig_StoreSplitHeroData takes nothing returns nothing set gg_trg_StoreSplitHeroData = CreateTrigger( ) call TriggerRegisterAnyUnitEventBJ( gg_trg_StoreSplitHeroData, EVENT_PLAYER_UNIT_SPELL_EFFECT) call TriggerAddCondition( gg_trg_StoreSplitHeroData, Condition( function Trig_StoreSplitHeroData_Conditions ) ) call TriggerAddAction( gg_trg_StoreSplitHeroData, function Trig_StoreSplitHeroData_Actions ) endfunction Leaks aside (I know there are a lot, my proirity is to get this working, then clean it), can anyone see whats wrong with my SplitHero_SplitKillCond function? See, the trigger linked to it should run when the Killer (not the Killed) unit is either Body or Mind. Debug shows me that the Killer is indeed either of those, but for some reason, it returns at false, as call BJDebugMsg("Yay!") is never shown and the actions never fire, instead, the Yay! message and the actions run when the conditions are not met (ie, when the killer is neither body or mind)! I know this used to work, but when i meade some crazy changes it suddendly stopped working, I ignore why. Help? |
| 06-28-2006, 12:03 PM | #2 |
JASS:call SetHandleHandle(SplitKillTrigger,"Caster",Caster) call SetHandleHandle(SplitExpirationTrigger,"Caster",Caster) call SetHandleHandle(Caster,"Body",Body) call SetHandleHandle(Caster,"Mind",Mind) call SetHandleHandle(SplitKillTrigger,"SplitExpirationTimer",SplitExpirationTrigger) That's where you're attaching variables to different other variables. Notice, you never attach Body or Mind to the trigger, but instead to the caster. Now we look at your condition.. JASS:local unit Body = GetHandleUnit(GetTriggeringTrigger(),"Body") local unit Mind = GetHandleUnit(GetTriggeringTrigger(),"Mind") What you should do in your condition is this for how you set it up. JASS:function SplitHero_SplitKillCond takes nothing returns boolean local unit Caster = GetHandleUnit(GetTriggeringTrigger(), "Caster") local unit Body = GetHandleUnit(Caster,"Body") local unit Mind = GetHandleUnit(Caster,"Mind") call BJDebugMsg("GetKillingUnit: "+GetUnitName(GetKillingUnit())) if GetKillingUnit() == Body or GetKillingUnit() == Mind then call BJDebugMsg("Yay!") return true endif return false endfunction This should fix your problem. |
| 06-28-2006, 02:15 PM | #3 |
I think we should have two version of attached var systems. One of them would store type information and warn if you try to grab the wrong type, which would also catch uninitialized data. Problem is that handle extensions automatically typecast to handles so we have a generic set for all handles. So switching to "SetHandleUnit" or the table equivalent would only be appropriate for new maps. For testing you would use the safe versions, then for production releases of the map you could just paste over the fast versions . Ex: JASS:function SetHandleUnit takes handle h, string name, function u returns nothing local string key = I2S(HtoI(h)) call StoreInteger(GC(),key,"data_"+name,HtoI(u)) call StoreString(GC(),key,"type_"+name,"Unit") endfunction function GetHandleUnit takes handle h, string name returns unit local string key = I2S(HtoI(h)) local string stype = GetStoredString(GC(),key,"type_"+name) if(stype != "Unit") then if(stype != "") then call BJDebugMsg("### Error: GetHandleUnit retrieved data of type "+stype) else call BJDebugMsg("### Warning: GetHandleUnit retrieved uninitialized data") endif endif return GetStoredInteger(GC(),key,"data_"+name) return null endfunction |
| 06-28-2006, 04:40 PM | #4 | |
Quote:
Gaaaah, that's the change I made I forgot to correct! T.T I knew it was gonna be something that silly, because as you can see, everywhere else the "extraction" is correct. Thanks a lot for pointing it out. I tend to overlook such details quite often. PipeDream: This is where it wold be nice to have a preprocessor, huh? ;P |
| 06-29-2006, 05:24 AM | #5 |
Hi again, thansk to you I got it to work greatly most of it. However, I don't know what is the relation, but now, whenever he casts the spell, the Caster unit won't respond to most of my commands. That is, if he is killing a group of units, he won't respond to any other command until he has killed them all. If i send him to patrol/escort an unit, he won't respond to anything at all until the unit dies. If it helps, the spell is based off Avatar and the script is the following: That Spellow Bastard:constant function SplitsExpirationTime takes nothing returns real return 30.00 endfunction constant function BodyType takes nothing returns integer return 'o003' endfunction constant function MindType takes nothing returns integer return 'o002' endfunction constant function SpawningFX takes nothing returns string return "Abilities\\Spells\\NightElf\\Blink\\BlinkTarget.mdl" endfunction function SplitHero_SplitsExpired takes nothing returns nothing local timer t = GetExpiredTimer() local trigger trg = GetHandleTrigger(t,"SplitKillTrigger") local unit Caster = GetHandleUnit(t,"Caster") local unit Body = GetHandleUnit(Caster,"Body") local unit Mind = GetHandleUnit(Caster,"Mind") local integer BonusAgi = GetHandleInt(t,"BonusAgi") local integer BonusStr = GetHandleInt(t,"BonusStr") local integer BonusInt = GetHandleInt(t,"BonusInt") local location CasterLoc= GetUnitLoc(Body) call DestroyEffect(AddSpecialEffectLoc("Abilities\\Spells\\NightElf\\Blink\\BlinkCaster.mdl",GetUnitLoc(Body))) call DestroyEffect(AddSpecialEffectLoc("Abilities\\Spells\\NightElf\\Blink\\BlinkCaster.mdl",GetUnitLoc(Mind))) call ShowUnitHide(Body) call ShowUnitHide(Mind) call SetUnitPositionLoc(Caster,CasterLoc) call SetHeroAgi(Caster,GetHeroAgi(Caster,false)+BonusAgi,true) call SetHeroStr(Caster,GetHeroStr(Caster,false)+BonusStr,true) call SetHeroInt(Caster,GetHeroInt(Caster,false)+BonusInt,true) call PauseUnit(Caster, false) call ShowUnitShow(Caster) call AddSpecialEffectTarget("Abilities\\Spells\\NightElf\\Blink\\BlinkTarget.mdl", Caster, "overhead") call SetHandleInt(t,"BonusAgi",0) call SetHandleInt(t,"BonusStr",0) call SetHandleInt(t,"BonusInt",0) call SetHandleHandle(t,"Caster",null) call SetHandleHandle(trg,"Caster",null) call SetHandleHandle(Caster,"Body",null) call SetHandleHandle(Caster,"Mind",null) call SetHandleHandle(trg,"SplitExpirationTimer",null) call SetHandleHandle(t,"SplitKillTrigger",null) set Caster = null set Body = null set Mind = null call RemoveLocation(CasterLoc) call DestroyTrigger(trg) endfunction function SplitHero_SplitKillCond takes nothing returns boolean local unit Caster = GetHandleUnit(GetTriggeringTrigger(),"Caster") local unit Body = GetHandleUnit(Caster,"Body") local unit Mind = GetHandleUnit(Caster,"Mind") local boolean flag = false if ( ( GetKillingUnit() == Body ) or ( GetKillingUnit() == Mind ) ) then set flag = true endif set Caster = null set Body = null set Mind = null return flag endfunction function SplitHero_SplitKill takes nothing returns nothing local timer t = GetHandleTimer(GetTriggeringTrigger(),"SplitExpirationTimer") local unit Caster = GetHandleUnit(GetTriggeringTrigger(),"Caster") local unit Body = GetHandleUnit(Caster,"Body") local unit Mind = GetHandleUnit(Caster,"Mind") local integer BonusAgi = 0 local integer BonusStr = 0 local integer BonusInt = 0 call BJDebugMsg("SplitHero_SplitKill initiated") set BonusAgi = GetHandleInt(t,"BonusAgi") set BonusStr = GetHandleInt(t,"BonusStr") set BonusInt = GetHandleInt(t,"BonusInt") if(GetKillingUnit() == Body) then set BonusAgi = BonusAgi + 1 set BonusStr = BonusStr + 2 elseif(GetKillingUnit() == Mind) then set BonusAgi = BonusAgi + 1 set BonusInt = BonusInt + 2 endif call BJDebugMsg("GetKillingUnit: "+GetUnitName(GetKillingUnit())) call BJDebugMsg("BonusStr: "+I2S(BonusStr)) call BJDebugMsg("BonusAgi: "+I2S(BonusAgi)) call BJDebugMsg("BonusInt: "+I2S(BonusInt)) call SetHandleInt(t,"BonusAgi",BonusAgi) call SetHandleInt(t,"BonusStr",BonusStr) call SetHandleInt(t,"BonusInt",BonusInt) set t = null set Caster = null set Body = null set Mind = null endfunction function SplitHero_StoreData takes nothing returns nothing local trigger SplitKillTrigger = CreateTrigger() local timer SplitExpirationTimer = CreateTimer() local unit Caster = GetTriggerUnit() local player p = GetOwningPlayer(Caster) local location CasterLoc= GetUnitLoc(Caster) local unit Body = CreateUnitAtLoc(p,BodyType(),OffsetLocation(CasterLoc, 128.00, 0),GetUnitFacing(Caster)) local unit Mind = CreateUnitAtLoc(p,MindType(),OffsetLocation(CasterLoc, -128.00, 0),GetUnitFacing(Caster)) call DestroyEffect(AddSpecialEffectTarget(SpawningFX(), Body, "overhead")) call DestroyEffect(AddSpecialEffectTarget(SpawningFX(), Mind, "overhead")) call PolledWait(0.25) call PauseUnit(Caster, true) call ShowUnitHide(Caster) if (p == GetLocalPlayer()) then call SelectUnit(Body, true) call SelectUnit(Mind, true) endif call SetHandleHandle(SplitKillTrigger,"Caster",Caster) call SetHandleHandle(SplitExpirationTimer,"Caster",Caster) call SetHandleHandle(Caster,"Body",Body) call SetHandleHandle(Caster,"Mind",Mind) call SetHandleHandle(SplitKillTrigger,"SplitExpirationTimer",SplitExpirationTimer) call SetHandleHandle(SplitExpirationTimer,"SplitKillTrigger",SplitKillTrigger) call UnitApplyTimedLife(Body, 'Bspl', SplitsExpirationTime() + 0.10) call UnitApplyTimedLife(Mind, 'Bspl', SplitsExpirationTime() + 0.10) call TimerStart(SplitExpirationTimer, SplitsExpirationTime() ,false, function SplitHero_SplitsExpired) call TriggerRegisterAnyUnitEventBJ( SplitKillTrigger, EVENT_PLAYER_UNIT_DEATH ) call TriggerAddCondition( SplitKillTrigger, Condition( function SplitHero_SplitKillCond ) ) call TriggerAddAction( SplitKillTrigger, function SplitHero_SplitKill ) call BJDebugMsg("SplitKillTrigger registered") call SetHandleHandle(GetTriggeringTrigger(),"Caster",null) call RemoveLocation(CasterLoc) endfunction //=========================================================================== function Trig_StoreSplitHeroData_Conditions takes nothing returns boolean return not(GetSpellAbilityId() != 'A003') endfunction function Trig_StoreSplitHeroData_Actions takes nothing returns nothing call SplitHero_StoreData() endfunction //=========================================================================== function InitTrig_StoreSplitHeroData takes nothing returns nothing set gg_trg_StoreSplitHeroData = CreateTrigger( ) call TriggerRegisterAnyUnitEventBJ( gg_trg_StoreSplitHeroData, EVENT_PLAYER_UNIT_SPELL_EFFECT) call TriggerAddCondition( gg_trg_StoreSplitHeroData, Condition( function Trig_StoreSplitHeroData_Conditions ) ) call TriggerAddAction( gg_trg_StoreSplitHeroData, function Trig_StoreSplitHeroData_Actions ) endfunction Possibly relevant functions are SplitHero_StoreData and SplitHero_SplitsExpired (if you have been wondering, yes, it is for the spell making session :P). Thanks in advance |
| 06-29-2006, 06:05 AM | #6 |
I cant really see why he would not respond to ANY commands at all. Nothing in there prevents him from taking commands, just a few pauses which are rectified and a hide/unhide setup. I'd really have to see the spell in action and know what exactly was going wrong and what exactly I should be looking for in the script. If you submit the preliminary to the spell session, we can view it and then suggest improvements or vital bug fixes. |
| 06-29-2006, 01:54 PM | #7 | |
Quote:
That's overkill also 10 types would make you need a couple of 100 different get functions |
| 06-29-2006, 03:18 PM | #8 | |
Quote:
Err, I'd prefer not submit it yet, it is in a rather emabarrasing state as it is right now, which is why I will post it here meanwhile. |
| 06-29-2006, 03:59 PM | #9 | |
Quote:
It seems to me that this is long overdue. |
| 06-29-2006, 07:59 PM | #10 |
Well Alev, I tested it multiple times, and aside from the spells on the split units not being very clean or well chosen, it appears to work. What did you mean the caster was being frozen before? I didn't witness any caster freeze errors in testing it. |
| 06-29-2006, 08:55 PM | #11 | ||
Quote:
Hence the "rather embarrasing" state. It was actually just a quick setup to test my spell, more balancing will come when I get the actual spell working right. Quote:
The caster doesn't freeze at all. As you might have seen, there are a few peasants you can kill. When you start killing them as the split units, and during the middle of the fight the spell 'times out' and the caster reassembles, the caster will start attacking the peasants, ignoring any other issue I give to him, until he has killed them all. Then, any order assigned cannot be interrumpted at all, liek if you order him to move somewhere, you cannot order him anything else until he reaches his destination. If you order him to patrol a unit, he won't stop unless the patrolled unit dies. |
| 06-29-2006, 09:59 PM | #12 |
I see.. That is very weird. I most likely blame WC3 itself. I don't think Storm, Earth, and Fire was meant to be used on already SEandF'd units, might weird the system out a bit. Your code doesn't appear to do anything regarding ignoring orders at all, so this sort of a bug wouldn't be associated with that. You might consider triggering the unit splits rather than using SEandF as the means. It would likely work then. |
| 06-29-2006, 10:12 PM | #13 | |
Quote:
Thing is, the current state of the spell (the one used by the hero, not the split units, which I need to change too) doesn't use SEaF (my original and the one used currently by the splits did, but couldn't find a way to track the spawns, gah), but Avatar (randomly picked spell, because it didn't need a target, I might consider using something else), and the split units are created manually. The error happens wether or not I use the SEaF spells on the split units. Gah. In any case, I will clean it up units wise, and post it already as my entry. |
| 06-30-2006, 12:04 AM | #14 |
I would use Berserk instead of Avatar. It might work that way, try it. Also, you could track the splits with dynamic triggers. If a split unit casts a split, create X and Y unit, attach them to trigger, etc. Might get complicated, but it would work. 'Tis a neat spell either way. :P |
| 06-30-2006, 01:06 AM | #15 | |||
Quote:
True that. Will certainly try it. Quote:
That's actually what I am doing with avatar :). What I meant is that when I was using SEaF, that was not possible (at least for me), since I could not truly figure out which units were spawned. Quote:
That's a compliment I didn't expect to see... Either way, I must get backl to work on that *POOF* |
