Edit: no longer necessary; got around that error (though, didn't solve it.)
//--------------------------------------------------------------------------
*full trigger at the bottom*
I have problems with arrays within struct arrays; somehow I override data in one array, when cleaning up another...
I'm working on a FF like battle zone and want store all creep data of an "enemy wave" in an struct, which itself is an struct array.
I want to spawn up to 5 units, store them in an struct array "EnemyWaves[]" of struct "EnemyData". Within that struct I have several arrays that
keep track of all the data for every unit within that wave.
So, I want to spawn the first wave: EnemyWaves[0], that contains 1 unit of type A; after that wave, I want to remove that wave EnemyWaves[0] and spawn the next wave EnemyWaves[1], which contains 1 unit of Type A and 2 units of Type B; ...
Now the problem is: when setting up or removing a wave, somehow the data gets overriden, and I have no idea what I'm doing wrong.
Through testing I always get down to these functions: "SetupWave", "SpawnNextWave" and the method ".reset"; but I can't figure it out.
This is the enemy setup that I'm calling
So it should come up:
First wave, 1 unit of type c001
Second wave, 1 unit of type c000, 2 units of type c001, 5 units max (there will be only 3 though)
Third wave, 5 units of type c001
Fourth wave, 1 unit of type c000
But what happens is:
First wave, 1 unit of type c001 (works)
Second wave, 2 units of type c001 (doesn't work); the first unit ".creepTypeId[0]" gets overriden/set to 0 in the ".reset" call of the PREVIOUS wave! so a unit is spawned of UnitType "0"
Now I leave out the ".reset" call and this happens:
First wave, works
Second wave, works
Third wave, doesn't work; instead of 5 units of type c001 there are 4 of c001 and 1 of c000
Fourth wave, works
Another weird thing (picture below):
-The picture on the left shows the unitType for every unit; the units slot within its wave; and the wave itself => this is all correct
-Now in the center picture there is the output of all the creepTypeIds of the second wave (EnemyWaves[1]); in the green box are the 3 units that will be spawned (which is correct), the "0" underneath would be the fourth unit (but I only set up 3 units; so this is correct, too). But the number underneath, the fifth unit, should be 0 as well! But it isn't. And I've never set it up. And I couldn't figure out where it does get setup.
-The picture on the right shows again the creepTypeId of the second wave; I gave out the creepId before the ".reset" call of the previous wave, and after. After the previous wave(&unit) gets destroyed, the first unit of the second wave gets also reset!
//--------------------------------------------------------------------------
*full trigger at the bottom*
I have problems with arrays within struct arrays; somehow I override data in one array, when cleaning up another...
I'm working on a FF like battle zone and want store all creep data of an "enemy wave" in an struct, which itself is an struct array.
I want to spawn up to 5 units, store them in an struct array "EnemyWaves[]" of struct "EnemyData". Within that struct I have several arrays that
keep track of all the data for every unit within that wave.
So, I want to spawn the first wave: EnemyWaves[0], that contains 1 unit of type A; after that wave, I want to remove that wave EnemyWaves[0] and spawn the next wave EnemyWaves[1], which contains 1 unit of Type A and 2 units of Type B; ...
Now the problem is: when setting up or removing a wave, somehow the data gets overriden, and I have no idea what I'm doing wrong.
Through testing I always get down to these functions: "SetupWave", "SpawnNextWave" and the method ".reset"; but I can't figure it out.
JASS:
function SetupWave takes integer whatWave, integer creepId, integer Min, integer Max returns nothing
local integer amount
local integer i = 0
local integer max
local integer min
local integer rand
...
// fills the array with the creepUnitTypeId, starting at the next empty slot.
set rand = GetRandomInt(min,max)
set amount = rand + EnemyWaves[whatWave].currentCreepSlot
set i = EnemyWaves[whatWave].currentCreepSlot
loop
exitwhen i >= amount
exitwhen i > I // can't get bigger than 'I' itself.
set EnemyWaves[whatWave].creepTypeId[i] = creepId
set i = i + 1
endloop
set EnemyWaves[whatWave].currentCreepSlot = i
...
endfunction
JASS:
function SpawnNextWave takes nothing returns nothing
local integer i = 0
// clear up the wave that came before! (doesn't run on first wave).
if currentWave >= 0 then
//call EnemyWaves[currentWave].reset() //<<<<<<<<<<<<<<<<<<<<<< problem?
set iWavesRemaining = iWavesRemaining - 1
endif
set currentWave = currentWave + 1
// creates units.
set i = 0
loop
exitwhen i >= EnemyWaves[currentWave].currentCreepSlot
exitwhen i >= EnemyWaves[currentWave].waveMaxUnits
//exitwhen EnemyWaves[currentWave].creepTypeId[i] == 0
call CreateCreep(EnemyWaves[currentWave].creepTypeId[i])
set i = i + 1
endloop
endfunction
JASS:
method reset takes nothing returns nothing
local integer i = 0
loop
exitwhen i > I
call .destroyCreep(i)
set .creepTypeId[i] = 0//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< problem?????
set i = i + 1
endloop
set .currentCreepSlot = 0
set .waveMaxUnits = 1
set iEnemiesAlive = 0
endmethod
This is the enemy setup that I'm calling
JASS:
call SetupWave(0, 'c001', 1, 1)
//call SetWaveMaxUnits(0,1)
call SetupWave(1, 'c000', 1, 1)
call SetupWave(1, 'c001', 2, 2)
call SetWaveMaxUnits(1,5)
call SetupWave(2, 'c001', 5, 5)
call SetupWave(3, 'c000', 1, 1)
First wave, 1 unit of type c001
Second wave, 1 unit of type c000, 2 units of type c001, 5 units max (there will be only 3 though)
Third wave, 5 units of type c001
Fourth wave, 1 unit of type c000
But what happens is:
First wave, 1 unit of type c001 (works)
Second wave, 2 units of type c001 (doesn't work); the first unit ".creepTypeId[0]" gets overriden/set to 0 in the ".reset" call of the PREVIOUS wave! so a unit is spawned of UnitType "0"
Now I leave out the ".reset" call and this happens:
First wave, works
Second wave, works
Third wave, doesn't work; instead of 5 units of type c001 there are 4 of c001 and 1 of c000
Fourth wave, works
Another weird thing (picture below):
-The picture on the left shows the unitType for every unit; the units slot within its wave; and the wave itself => this is all correct
-Now in the center picture there is the output of all the creepTypeIds of the second wave (EnemyWaves[1]); in the green box are the 3 units that will be spawned (which is correct), the "0" underneath would be the fourth unit (but I only set up 3 units; so this is correct, too). But the number underneath, the fifth unit, should be 0 as well! But it isn't. And I've never set it up. And I couldn't figure out where it does get setup.
-The picture on the right shows again the creepTypeId of the second wave; I gave out the creepId before the ".reset" call of the previous wave, and after. After the previous wave(&unit) gets destroyed, the first unit of the second wave gets also reset!
JASS:
/***************************************************************
* creates, spawns && handles enemies and enemy groups!
***************************************************************/
library EnemySystem initializer Init requires UnitDataList, FadeInFadeOut
globals
private constant real FACING = 270. //
private constant real X = -15000 // an empty spot to spawn units.
private constant real Y = -15000 // an empty spot to spawn units.
//-----------------------------
private constant integer I = 4 // the maximum number (starting to count at 0) of enemies on the field.
endglobals
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
struct EnemyData// Enemy as a whole, not as a single creep.
CreepData array creepData[I] // keeps track of the invidiual CreepData.
TempoData array tempoData[I] // keeps track of the individual tempodata for this Creep.
unit array creeps[I] // stores the actual creeps within this wave.
integer array creepTypeId[I] // stores the creepTypeId of the creep to be spawned.
integer currentCreepSlot = 0 // used for setting up creeps
integer waveMaxUnits = 1 // max units per wave.
method createUnit takes integer uId, integer i returns nothing
set .creepData[i] = createCreep(uId,X,Y,FACING)
set .tempoData[i] = createTempoData(.creepData[i].Unit)
set .creeps[i] = .creepData[i].Unit
set iEnemiesAlive = iEnemiesAlive + 1 // global call, header.
endmethod
method createUnitFadeIn takes integer uId, integer i returns nothing
local Fade f
call .createUnit(uId, i)
set f = Fade.create(true, .creepData[i].Unit)
endmethod
method destroyCreep takes integer i returns nothing
//call killTempoData(this.tempoData[i])
call killTempoDataUnit(.creeps[i])
if CheckUnitIsAlive(.creeps[i]) then
set iEnemiesAlive = iEnemiesAlive - 1
endif
call .creepData[i].destroy()
set .creeps[i] = null
set .tempoData[i] = -1
set .creepData[i] = -1
endmethod
method reset takes nothing returns nothing
local integer i = 0
loop
exitwhen i > I
call .destroyCreep(i)
set .creepTypeId[i] = 0//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< problem?????
set i = i + 1
endloop
set .currentCreepSlot = 0
set .waveMaxUnits = 1
set iEnemiesAlive = 0
endmethod
method onDestroy takes nothing returns nothing
call .reset()
endmethod
endstruct
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
globals
EnemyData array EnemyWaves // all waves to come are stored in here in chronological order
private integer iWavesAmount = 0
integer iWavesRemaining = 0 // keeps track of how many to come
private integer currentWave = -1
endglobals
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
private function getFreeSlot takes nothing returns integer
/**
we first check if ANY slot is free;
if there is none we run again and check if ANY
unit is dead! if so: we will remove that
unit and replace it with the new one!
**/
local integer i = 0
loop
exitwhen i > 4
if EnemyWaves[currentWave].creeps[i] == null then
return i
endif
set i = i + 1
endloop
set i = 0
loop
exitwhen i > 4
if not CheckUnitIsAlive(EnemyWaves[currentWave].creeps[i]) then
call EnemyWaves[currentWave].destroyCreep(i)
return i
endif
set i = i + 1
endloop
return 5 //0 is lowest, 4 is highest; 5 is "null" or "false".
endfunction
//-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
function CreateCreep takes integer uId returns unit
local real x
local real y
local integer i
local unit u
// we first check if there is a free slot on the battle field.
set i = getFreeSlot()
if i >= 0 and i <= 4 then
set x = GetLocationX(EnemyFormationSetup[CurrentFormation].location[i])
set y = GetLocationY(EnemyFormationSetup[CurrentFormation].location[i])
// create unit and setup position.
call EnemyWaves[currentWave].createUnitFadeIn(uId, i)
set u = EnemyWaves[currentWave].creeps[i]
call SetUnitPosition(u, x, y)
set BLocDefaultX[GetUnitId(u)] = GetUnitX(u)
set BLocDefaultY[GetUnitId(u)] = GetUnitY(u)
// outside reference.
set TempoSystem_tempoDataEnemy[i].owningUnit = u
set TempoSystem_tempoDataEnemy[i].owningUnitId = GetUnitId(u)
// Yarr!! Harr!!
call SetUnitAnimation(u, "stand ready")
//-----------------
set u = null
return u
endif
//-----------------
set u = null
return null
endfunction
//-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
function SetWaveMaxUnits takes integer whatWave, integer max returns nothing
set EnemyWaves[whatWave].waveMaxUnits = max
endfunction
//-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
function SetupWave takes integer whatWave, integer creepId, integer Min, integer Max returns nothing
local EnemyData ed = EnemyWaves[whatWave]
local integer amount
local integer i = 0
local integer max
local integer min
local integer rand
// makes sure the input values are within boundaries.
if Max > 5 then
set max = 5
else
set max = Max
endif
if Min < 0 then
set min = 0
else
set min = Min
endif
// fills the array with the creepUnitTypeId, starting at the next empty slot.
set rand = GetRandomInt(min,max)
set amount = rand + EnemyWaves[whatWave].currentCreepSlot
set i = EnemyWaves[whatWave].currentCreepSlot
loop
exitwhen i >= amount
exitwhen i > I // can't get bigger than 'I' itself.
set EnemyWaves[whatWave].creepTypeId[i] = creepId // ???????????????????????????????????????????????????????
set i = i + 1
endloop
set EnemyWaves[whatWave].currentCreepSlot = i
// sets the number of max units automatically.
// can be set manually, too (SetWaveMaxUnits).
if rand > EnemyWaves[whatWave].waveMaxUnits then
set EnemyWaves[whatWave].waveMaxUnits = rand
if rand > 5 then
set EnemyWaves[whatWave].waveMaxUnits = 5
endif
endif
// sets the number of maximum waves to come.
if iWavesAmount < whatWave then
set iWavesAmount = whatWave
set iWavesRemaining = whatWave
endif
endfunction
//-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
function CleanUpWaves takes nothing returns nothing
local integer i = 0
loop
exitwhen i > 99
call EnemyWaves[i].reset()
set i = i + 1
endloop
set iWavesAmount = 0
set iWavesRemaining = 0
set currentWave = -1
endfunction
//-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
function SpawnNextWave takes nothing returns nothing
local integer i = 0
// clear up the wave that came before! (doesn't run on first wave).
if currentWave >= 0 then
call EnemyWaves[currentWave].reset() //<<<<<<<<<<<<<<<<<<<<<< problem?
set iWavesRemaining = iWavesRemaining - 1
endif
set currentWave = currentWave + 1
// creates units.
set i = 0
loop
exitwhen i >= EnemyWaves[currentWave].currentCreepSlot
exitwhen i >= EnemyWaves[currentWave].waveMaxUnits
//exitwhen EnemyWaves[currentWave].creepTypeId[i] == 0
call CreateCreep(EnemyWaves[currentWave].creepTypeId[i])
set i = i + 1
endloop
endfunction
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
private function Init takes nothing returns nothing
local integer i = 0
local integer j = 0
loop
exitwhen i > 99
set EnemyWaves[i] = EnemyData.create()
set j = 0
loop
exitwhen j > I
set EnemyWaves[i].creepTypeId[j] = 0
set j = j + 1
endloop
set i = i + 1
endloop
endfunction
endlibrary
Last edited: