| 09-28-2008, 08:30 PM | #1 |
This ability is supposed to enable link towers (towers in link mode) to power up attacking towers (towers in normal mode), and be able to do it a limited number of times per second (up to 3 times a second). Here is the code: JASS:scope Prism //======================= globals private constant integer TOWERID_1 = 'n022' //This is the id of the actual Prism Tower. (LINK MODE) private constant integer TOWERID_2 = 'n02C' //This is the id of the actual Prism Tower. (LINK MODE) //private constant integer PWRUPID = 'A046' //This is the id of the power up ability in the object editor. private constant real RANGE = 700.0 //This is the range of the tower - it will be used to determine how far the towers will look for support towers. private constant real DAMAGE1 = 2000.0 //This is how much damage a powering up tower does. private constant real DAMAGE2 = 10000.0 //This is how much damage a powering up tower does. private constant real BASE1 = 4000.0 //This is how much damage an attacking tower does normally. private constant real BASE2 = 20000.0 //This is how much damage an attacking tower does normally. //private constant real EXPONENT = 1.05 //This determines the factor that each tower adds to the damage of the shot. private constant real COOLDOWN = 0.33 //This is the cooldown of the Prism Tower's attack. //private constant string ORDERSTRING = "spiritlink" //This is the Order String of the effect ability. endglobals //======================= //======================= globals private unit CurrentTower = null private integer array TowerValues private lightning array LightningList private unit array tempArray private group mainP = CreateGroup() private timer Tprism = CreateTimer() private integer Total = 0 private Prism_data array structArray //private real tempPower private integer tempCount endglobals //======================= //======================================================================================= //needed struct struct Prism_data unit array towers integer size method Start_Prism takes unit array chain, takes integer count returns nothing set .towers = chain set .size = count endmethod method onDestroy takes nothing returns nothing loop exitwhen .size < 0 //call UnitRemoveAbility(towerChain[i], PWRUPID) set TowerValues[GetUnitIndex(.towers[i])] = TowerValues[GetUnitIndex(.towers[i])] - 1 call DestroyLightning(LightningList[GetUnitIndex(.towers[i])]) set .towers[i] = null set .size = .size - 1 endloop endmethod endstruct //movement and effects function Prism_Go takes nothing returns nothing local integer i = 1 local Prism_data dat loop exitwhen i > Total set dat = structArray[i] call dat.destroy() set structArray[i] = structArray[Total] set Total = Total - 1 endloop if Total==0 then call PauseTimer(Tprism) endif //call Msg("Run",Player(0)) endfunction private function TowerFilter1 takes nothing returns boolean return GetOwningPlayer(GetFilterUnit()) == GetOwningPlayer(GetEventDamageSource()) and GetUnitTypeId(GetFilterUnit()) == TOWERID_1 and TowerValues[GetUnitIndex(GetFilterUnit())] < 3 and GetUnitCurrentOrder(GetFilterUnit()) == OrderId("none") and GetFilterUnit() != CurrentTower and GetWidgetLife(GetFilterUnit()) > 0.405 endfunction private function TowerFilter2 takes nothing returns boolean return GetOwningPlayer(GetFilterUnit()) == GetOwningPlayer(GetEventDamageSource()) and GetUnitTypeId(GetFilterUnit()) == TOWERID_2 and TowerValues[GetUnitIndex(GetFilterUnit())] < 3 and GetUnitCurrentOrder(GetFilterUnit()) == OrderId("none") and GetFilterUnit() != CurrentTower and GetWidgetLife(GetFilterUnit()) > 0.405 endfunction private function TowerForGroup takes nothing returns nothing // use our globals here //set tempPower = tempPower * EXPONENT set tempCount = tempCount + 1 set tempArray[tempCount] = GetEnumUnit() set TowerValues[GetUnitIndex(GetEnumUnit())] = TowerValues[GetUnitIndex(GetEnumUnit())] + 1 endfunction //starts the effects function Trig_Prism_Actions takes nothing returns nothing local real x = GetUnitX(GetEventDamageSource()) local real y = GetUnitY(GetEventDamageSource()) local real x1 local real y1 //local real power = EXPONENT local real bonus local real dam local integer towerChainCount = 0 local integer i local unit attacker = GetEventDamageSource() local unit array towerChain local Prism_data dat //Fire Up bonus damage if GetUnitAbilityLevel(attacker, 'B00A') > 0 then set bonus = 1.25 elseif GetUnitAbilityLevel(attacker, 'B00J') > 0 then set bonus = 1.5 elseif GetUnitAbilityLevel(attacker, 'B00K') > 0 then set bonus = 3.0 else set bonus = 1.0 endif //Get available towers and add them to the array. set CurrentTower = attacker set TowerValues[GetUnitIndex(CurrentTower)] = TowerValues[GetUnitIndex(CurrentTower)] + 1 set TowerChain[0] = CurrentTower set x = GetUnitX(CurrentTower) set y = GetUnitY(CurrentTower) call GroupClear(mainP) if GetUnitTypeId(attacker)==TOWER_GOLEM then call GroupEnumUnitsInRange(mainP, x, y, RANGE, Condition(function TowerFilter1)) elseif GetUnitTypeId(attacker)==TOWER_ABOMINATION then call GroupEnumUnitsInRange(mainP, x, y, RANGE, Condition(function TowerFilter2)) endif // Set out temp globals to their values before we call the ForGroup() set tempArray = towerChain //set tempPower = power set tempCount = towerChainCount // now we can use these globals in the forgroup call ForGroup(mainP,function TowerForGroup) // no we setback each local we will use with the global from the group set towerChainCount = tempCount set towerChain = tempArray // I don't think this is needed since the array reference never changes, only the values in it //set power = tempPower //Go through each tower, starting at the end, add the power up ability and order it to fire. set i = towerChainCount loop exitwhen i == 0 //call UnitAddAbility(towerChain[i], PWRUPID) //call IssueTargetOrder(towerChain[i], ORDERSTRING, towerChain[0]) set LightningList[GetUnitIndex(towerChain[i])] = AddLightningEx("MFPB",true,GetUnitX(towerChain[i]),GetUnitY(towerChain[i]),50.,GetUnitX(towerChain[0]),GetUnitY(towerChain[0]),50.) set i = i - 1 endloop //Add the power up damage, checking for additional towers and making sure the unit is not out of range. if GetUnitTypeId(attacker)==TOWER_GOLEM then set dam = BASE1 + (DAMAGE1 * towerChainCount) //* power elseif GetUnitTypeId(attacker)==TOWER_ABOMINATION then set dam = BASE2 + (DAMAGE2 * towerChainCount) //* power endif set dam = dam*bonus call UnitDamageTarget(attacker, GetTriggerUnit(), dam, false, false, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_NORMAL, null) call TextTagUnit(I2S(R2I(dam)),GetTriggerUnit(),255,0,0,200,.03,2.) set dat = Prism_data.create() call dat.Start_Prism(towerChain,towerChainCount) set Total = Total + 1 set structArray[Total] = dat if Total==1 then call TimerStart(Tprism,COOLDOWN,false,function Prism_Go) endif set attacker = null endfunction endscope //==== Init Trigger Prism ==== function InitTrig_Prism takes nothing returns nothing call ORBEngine_RegisterOrb(TOWER_GOLEM, function Trig_Prism_Actions, "TOWER_GOLEM: Prism") call ORBEngine_RegisterOrb(TOWER_ABOMINATION, function Trig_Prism_Actions, "TOWER_ABOMINATION: Prism") endfunction Error gives [Size] expected, and the code for that is: JASS:struct Prism_data unit array towers integer size If you see ways to optimize the code that is also always appreciated. |
| 09-28-2008, 09:17 PM | #2 |
Arrays in structs always need defined sizes, so you could make it like unit array towers [15] |
| 09-28-2008, 09:37 PM | #3 |
Is there a way to make it dynamic? There could potentially be a lot of units in this array, but I also don't want to overshoot it. Any ideas? As for the code, does it work the way I think it does? I envisioned a link being drawn from as having a counter added to it, and when it has 3 counters it cannot link anymore. However, every 0.33 seconds after a counter is added, it is removed thus serving as a CD. Does it look optimized? I haven't been JASSing as long as others have on these forums, so do feel free to critique the code. |
| 09-28-2008, 10:06 PM | #4 |
If you want it to be dynamic, you don't want an array. Think gamecache, or more likely useful for this, a unit group. The reason you have to specify the max size is because the number of structs allocateable = 8192 (or different if you spec a higher limit) / (largest max array index in the struct). |
| 09-28-2008, 11:47 PM | #5 |
You could just increase the size of the struct: JASS:struct Prism_data[64000] unit array towers[200] |
| 09-28-2008, 11:51 PM | #6 |
Yes, but you're then eating up a ridiculous amount of array indexes for no good reason. |
| 09-29-2008, 01:42 AM | #7 |
But why bother when alternatives tend to make more sense? |
| 09-29-2008, 04:01 AM | #8 |
JASS:method Start_Prism takes unit array chain, integer count returns nothing set .towers = chain set .size = count endmethod Error: expected returns...??? Full code: JASS:scope Prism //======================= globals private constant integer TOWERID_1 = 'n022' //This is the id of the actual Prism Tower. (LINK MODE) private constant integer TOWERID_2 = 'n02C' //This is the id of the actual Prism Tower. (LINK MODE) //private constant integer PWRUPID = 'A046' //This is the id of the power up ability in the object editor. private constant real RANGE = 700.0 //This is the range of the tower - it will be used to determine how far the towers will look for support towers. private constant real DAMAGE1 = 2000.0 //This is how much damage a powering up tower does. private constant real DAMAGE2 = 10000.0 //This is how much damage a powering up tower does. private constant real BASE1 = 4000.0 //This is how much damage an attacking tower does normally. private constant real BASE2 = 20000.0 //This is how much damage an attacking tower does normally. //private constant real EXPONENT = 1.05 //This determines the factor that each tower adds to the damage of the shot. private constant real COOLDOWN = 0.33 //This is the cooldown of the Prism Tower's attack. //private constant string ORDERSTRING = "spiritlink" //This is the Order String of the effect ability. endglobals //======================= //======================= globals private unit CurrentTower = null private integer array TowerValues private lightning array LightningList private unit array tempArray private group mainP = CreateGroup() private timer Tprism = CreateTimer() private integer Total = 0 private Prism_data array structArray //private real tempPower private integer tempCount endglobals //======================= //======================================================================================= //needed struct struct Prism_data unit array towers [500] integer size method Start_Prism takes unit array chain, integer count returns nothing set .towers = chain set .size = count endmethod method onDestroy takes nothing returns nothing loop exitwhen .size < 0 //call UnitRemoveAbility(towerChain[i], PWRUPID) set TowerValues[GetUnitIndex(.towers[i])] = TowerValues[GetUnitIndex(.towers[i])] - 1 call DestroyLightning(LightningList[GetUnitIndex(.towers[i])]) set .towers[i] = null set .size = .size - 1 endloop endmethod endstruct //movement and effects function Prism_Go takes nothing returns nothing local integer i = 1 local Prism_data dat loop exitwhen i > Total set dat = structArray[i] call dat.destroy() set structArray[i] = structArray[Total] set Total = Total - 1 endloop if Total==0 then call PauseTimer(Tprism) endif //call Msg("Run",Player(0)) endfunction private function TowerFilter1 takes nothing returns boolean return GetOwningPlayer(GetFilterUnit()) == GetOwningPlayer(GetEventDamageSource()) and GetUnitTypeId(GetFilterUnit()) == TOWERID_1 and TowerValues[GetUnitIndex(GetFilterUnit())] < 3 and GetUnitCurrentOrder(GetFilterUnit()) == OrderId("none") and GetFilterUnit() != CurrentTower and GetWidgetLife(GetFilterUnit()) > 0.405 endfunction private function TowerFilter2 takes nothing returns boolean return GetOwningPlayer(GetFilterUnit()) == GetOwningPlayer(GetEventDamageSource()) and GetUnitTypeId(GetFilterUnit()) == TOWERID_2 and TowerValues[GetUnitIndex(GetFilterUnit())] < 3 and GetUnitCurrentOrder(GetFilterUnit()) == OrderId("none") and GetFilterUnit() != CurrentTower and GetWidgetLife(GetFilterUnit()) > 0.405 endfunction private function TowerForGroup takes nothing returns nothing // use our globals here //set tempPower = tempPower * EXPONENT set tempCount = tempCount + 1 set tempArray[tempCount] = GetEnumUnit() set TowerValues[GetUnitIndex(GetEnumUnit())] = TowerValues[GetUnitIndex(GetEnumUnit())] + 1 endfunction //starts the effects function Trig_Prism_Actions takes nothing returns nothing local real x = GetUnitX(GetEventDamageSource()) local real y = GetUnitY(GetEventDamageSource()) local real x1 local real y1 //local real power = EXPONENT local real bonus local real dam local integer towerChainCount = 0 local integer i local unit attacker = GetEventDamageSource() local unit array towerChain local Prism_data dat //Fire Up bonus damage if GetUnitAbilityLevel(attacker, 'B00A') > 0 then set bonus = 1.25 elseif GetUnitAbilityLevel(attacker, 'B00J') > 0 then set bonus = 1.5 elseif GetUnitAbilityLevel(attacker, 'B00K') > 0 then set bonus = 3.0 else set bonus = 1.0 endif //Get available towers and add them to the array. set CurrentTower = attacker set TowerValues[GetUnitIndex(CurrentTower)] = TowerValues[GetUnitIndex(CurrentTower)] + 1 set TowerChain[0] = CurrentTower set x = GetUnitX(CurrentTower) set y = GetUnitY(CurrentTower) call GroupClear(mainP) if GetUnitTypeId(attacker)==TOWER_GOLEM then call GroupEnumUnitsInRange(mainP, x, y, RANGE, Condition(function TowerFilter1)) elseif GetUnitTypeId(attacker)==TOWER_ABOMINATION then call GroupEnumUnitsInRange(mainP, x, y, RANGE, Condition(function TowerFilter2)) endif // Set out temp globals to their values before we call the ForGroup() set tempArray = towerChain //set tempPower = power set tempCount = towerChainCount // now we can use these globals in the forgroup call ForGroup(mainP,function TowerForGroup) // no we setback each local we will use with the global from the group set towerChainCount = tempCount set towerChain = tempArray // I don't think this is needed since the array reference never changes, only the values in it //set power = tempPower //Go through each tower, starting at the end, add the power up ability and order it to fire. set i = towerChainCount loop exitwhen i == 0 //call UnitAddAbility(towerChain[i], PWRUPID) //call IssueTargetOrder(towerChain[i], ORDERSTRING, towerChain[0]) set LightningList[GetUnitIndex(towerChain[i])] = AddLightningEx("MFPB",true,GetUnitX(towerChain[i]),GetUnitY(towerChain[i]),50.,GetUnitX(towerChain[0]),GetUnitY(towerChain[0]),50.) set i = i - 1 endloop //Add the power up damage, checking for additional towers and making sure the unit is not out of range. if GetUnitTypeId(attacker)==TOWER_GOLEM then set dam = BASE1 + (DAMAGE1 * towerChainCount) //* power elseif GetUnitTypeId(attacker)==TOWER_ABOMINATION then set dam = BASE2 + (DAMAGE2 * towerChainCount) //* power endif set dam = dam*bonus call UnitDamageTarget(attacker, GetTriggerUnit(), dam, false, false, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_NORMAL, null) call TextTagUnit(I2S(R2I(dam)),GetTriggerUnit(),255,0,0,200,.03,2.) set dat = Prism_data.create() call dat.Start_Prism(towerChain,towerChainCount) set Total = Total + 1 set structArray[Total] = dat if Total==1 then call TimerStart(Tprism,COOLDOWN,false,function Prism_Go) endif set attacker = null endfunction endscope //==== Init Trigger Prism ==== function InitTrig_Prism takes nothing returns nothing call ORBEngine_RegisterOrb(TOWER_GOLEM, function Trig_Prism_Actions, "TOWER_GOLEM: Prism") call ORBEngine_RegisterOrb(TOWER_ABOMINATION, function Trig_Prism_Actions, "TOWER_ABOMINATION: Prism") endfunction |
| 09-29-2008, 04:04 AM | #9 |
JASS:method Start_Prism takes unit array chain, integer count returns nothing set .towers = chain set .size = count endmethod JASS:type UnitArray extends unit array[SIZE] ... method Start_Prism takes UnitArray chain, integer count returns nothing set .towers = chain set .size = count endmethod |
| 09-29-2008, 04:54 AM | #10 |
After making such changes, I have gotten the code to compile and save. However, when tested in-game nothing happens...at all. JASS:scope Prism //======================= globals private constant integer TOWERID_1 = 'n022' //This is the id of the actual Prism Tower. (LINK MODE) private constant integer TOWERID_2 = 'n02C' //This is the id of the actual Prism Tower. (LINK MODE) //private constant integer PWRUPID = 'A046' //This is the id of the power up ability in the object editor. private constant real RANGE = 700.0 //This is the range of the tower - it will be used to determine how far the towers will look for support towers. private constant real DAMAGE1 = 2000.0 //This is how much damage a powering up tower does. private constant real DAMAGE2 = 10000.0 //This is how much damage a powering up tower does. private constant real BASE1 = 4000.0 //This is how much damage an attacking tower does normally. private constant real BASE2 = 20000.0 //This is how much damage an attacking tower does normally. //private constant real EXPONENT = 1.05 //This determines the factor that each tower adds to the damage of the shot. private constant real COOLDOWN = 0.33 //This is the cooldown of the Prism Tower's attack. //private constant string ORDERSTRING = "spiritlink" //This is the Order String of the effect ability. endglobals //======================= //======================= type UnitArray extends unit array[500] globals private unit CurrentTower = null private integer array TowerValues private lightning array LightningList private UnitArray tempArray private group mainP = CreateGroup() private timer Tprism = CreateTimer() private integer Total = 0 private Prism_data array structArray //private real tempPower private integer tempCount endglobals //======================= //======================================================================================= //needed struct struct Prism_data UnitArray towers integer size method Start_Prism takes UnitArray chain, integer count returns nothing set .towers = chain set .size = count endmethod method onDestroy takes nothing returns nothing loop exitwhen .size < 0 //call UnitRemoveAbility(towerChain[i], PWRUPID) set TowerValues[GetUnitIndex(.towers[.size])] = TowerValues[GetUnitIndex(.towers[.size])] - 1 call DestroyLightning(LightningList[GetUnitIndex(.towers[.size])]) set .towers[.size] = null set .size = .size - 1 endloop endmethod endstruct //movement and effects function Prism_Go takes nothing returns nothing local integer i = 1 local Prism_data dat loop exitwhen i > Total set dat = structArray[i] call dat.destroy() set structArray[i] = structArray[Total] set Total = Total - 1 endloop if Total==0 then call PauseTimer(Tprism) endif //call Msg("Run",Player(0)) endfunction private function TowerFilter1 takes nothing returns boolean return GetOwningPlayer(GetFilterUnit()) == GetOwningPlayer(GetEventDamageSource()) and GetUnitTypeId(GetFilterUnit()) == TOWERID_1 and TowerValues[GetUnitIndex(GetFilterUnit())] < 3 and GetUnitCurrentOrder(GetFilterUnit()) == OrderId("none") and GetFilterUnit() != CurrentTower and GetWidgetLife(GetFilterUnit()) > 0.405 endfunction private function TowerFilter2 takes nothing returns boolean return GetOwningPlayer(GetFilterUnit()) == GetOwningPlayer(GetEventDamageSource()) and GetUnitTypeId(GetFilterUnit()) == TOWERID_2 and TowerValues[GetUnitIndex(GetFilterUnit())] < 3 and GetUnitCurrentOrder(GetFilterUnit()) == OrderId("none") and GetFilterUnit() != CurrentTower and GetWidgetLife(GetFilterUnit()) > 0.405 endfunction private function TowerForGroup takes nothing returns nothing // use our globals here //set tempPower = tempPower * EXPONENT set tempCount = tempCount + 1 set tempArray[tempCount] = GetEnumUnit() set TowerValues[GetUnitIndex(GetEnumUnit())] = TowerValues[GetUnitIndex(GetEnumUnit())] + 1 endfunction //starts the effects function Trig_Prism_Actions takes nothing returns nothing local real x = GetUnitX(GetEventDamageSource()) local real y = GetUnitY(GetEventDamageSource()) local real x1 local real y1 //local real power = EXPONENT local real bonus local real dam local integer towerChainCount = 0 local integer i local unit attacker = GetEventDamageSource() local UnitArray towerChain local Prism_data dat //Fire Up bonus damage if GetUnitAbilityLevel(attacker, 'B00A') > 0 then set bonus = 1.25 elseif GetUnitAbilityLevel(attacker, 'B00J') > 0 then set bonus = 1.5 elseif GetUnitAbilityLevel(attacker, 'B00K') > 0 then set bonus = 3.0 else set bonus = 1.0 endif //Get available towers and add them to the array. set CurrentTower = attacker set TowerValues[GetUnitIndex(CurrentTower)] = TowerValues[GetUnitIndex(CurrentTower)] + 1 set towerChain[0] = CurrentTower set x = GetUnitX(CurrentTower) set y = GetUnitY(CurrentTower) call GroupClear(mainP) if GetUnitTypeId(attacker)==TOWER_GOLEM then call GroupEnumUnitsInRange(mainP, x, y, RANGE, Condition(function TowerFilter1)) elseif GetUnitTypeId(attacker)==TOWER_ABOMINATION then call GroupEnumUnitsInRange(mainP, x, y, RANGE, Condition(function TowerFilter2)) endif // Set out temp globals to their values before we call the ForGroup() set tempArray = towerChain //set tempPower = power set tempCount = towerChainCount // now we can use these globals in the forgroup call ForGroup(mainP,function TowerForGroup) // no we setback each local we will use with the global from the group set towerChainCount = tempCount set towerChain = tempArray // I don't think this is needed since the array reference never changes, only the values in it //set power = tempPower //Go through each tower, starting at the end, add the power up ability and order it to fire. set i = towerChainCount loop exitwhen i == 0 //call UnitAddAbility(towerChain[i], PWRUPID) //call IssueTargetOrder(towerChain[i], ORDERSTRING, towerChain[0]) set LightningList[GetUnitIndex(towerChain[i])] = AddLightningEx("MFPB",true,GetUnitX(towerChain[i]),GetUnitY(towerChain[i]),50.,GetUnitX(towerChain[0]),GetUnitY(towerChain[0]),50.) set i = i - 1 endloop //Add the power up damage, checking for additional towers and making sure the unit is not out of range. if GetUnitTypeId(attacker)==TOWER_GOLEM then set dam = BASE1 + (DAMAGE1 * towerChainCount) //* power elseif GetUnitTypeId(attacker)==TOWER_ABOMINATION then set dam = BASE2 + (DAMAGE2 * towerChainCount) //* power endif set dam = dam*bonus call UnitDamageTarget(attacker, GetTriggerUnit(), dam, false, false, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_NORMAL, null) call TextTagUnit(I2S(R2I(dam)),GetTriggerUnit(),255,0,0,200,.03,2.) set dat = Prism_data.create() call dat.Start_Prism(towerChain,towerChainCount) set Total = Total + 1 set structArray[Total] = dat if Total==1 then call TimerStart(Tprism,COOLDOWN,false,function Prism_Go) endif set attacker = null endfunction endscope //==== Init Trigger Prism ==== function InitTrig_Prism takes nothing returns nothing call ORBEngine_RegisterOrb(TOWER_GOLEM, function Trig_Prism_Actions, "TOWER_GOLEM: Prism") call ORBEngine_RegisterOrb(TOWER_ABOMINATION, function Trig_Prism_Actions, "TOWER_ABOMINATION: Prism") endfunction |
| 09-29-2008, 06:44 AM | #11 |
I haven't bothered reading your code, but I had a similar issue with my rally point system. My solution was to use Linked Lists, but in your case a group is probably better. |
| 09-29-2008, 07:21 AM | #12 |
Could a linked list be applicable? |
| 09-29-2008, 06:26 PM | #13 |
do you want me to take another stab at this? - looks like your trying a completely different spell then what was originally intended however |
| 09-29-2008, 09:37 PM | #14 | |
Quote:
Hey, ya that would be great. Indeed I am trying something different, and I can get on AIM/MSN to discuss this. I'm really confused as to why the spell stopped working after these changes. I've looked over the code several times, and it should be working fine. Even if it doesn't count the link units correctly, the attacking tower should still be doing its base damage (as if there were 0 links). Yet nothing fires... |
| 09-30-2008, 03:57 AM | #15 |
struct is already an array... nested arrays not allowed. use alternate struct allocator and be happy. |
