| 09-10-2008, 03:48 PM | #1 |
Hi guys, I am going to make a mind mastery spell. This spell affects all enemy units inside a region and changes their owner for a period of time. However I have a problem .... Changing their owner is kinda easy ... problem is, how do I get him back ? I saw people using "SetUserData" but that is definitely something I don't want to use. I also though of adding the units to a group, but then I wouldn't be able to know their original owners .... Finally I though, maybe I can place units and their player in two parallel arrays, but then I remembered I would never know the amount of units inside the AOE of the spell. Can some one help me find a solution for this problem ? |
| 09-10-2008, 04:53 PM | #2 |
Have you considered using a different group for each original owner? |
| 09-10-2008, 05:11 PM | #3 |
So, there are 12 different players, I can use a group array and than I just move unit in/out of those groups. Sounds a better solution than using dinamic arrays ! Thx xD PS:this will be my next submitted spell ! |
| 09-10-2008, 05:37 PM | #4 |
Make sure you make the spell support multiple instances so that units are not given back tithe wrong player on multiple casts. |
| 09-10-2008, 05:43 PM | #5 | |
Quote:
|
| 09-10-2008, 08:12 PM | #6 | ||
Quote:
Quote:
- Selects all enemy units in the target AOE and confuses them, by changing their owners for an amount of time. This sounds simple doesn't it ? Well, but it's not ! I am going to make of this a fun spell, so every player in game has a chance of controlling the unit ! like Player 1 has 10% chance, player 2 has 10% ... you get the point. Then when you cast the spell, total confusion is spread ! xD However I am having trouble in changing the owners of the units when I cast the spell. When it ends is easy, problem is when I cast it ... I am going to make another thread, asking for an opinion, because making vJASS spells is easy, but making them JESP ... is another story xD |
| 09-10-2008, 11:15 PM | #7 | |
Quote:
|
| 09-10-2008, 11:20 PM | #8 |
Doing something static and something versatile is never the same thing, and it will never be. Statics are always easier. A JESP spell is not static, it can not be, because it must support change without allowing the user to enter the spell's core. |
| 09-11-2008, 01:23 AM | #9 |
If you use structural data for each unit (assign all this stuff in a create method) and associate said struct instance to the unit (I like PUI for it) your spell will be versatile and 8191 units can be affected at the same time. All the data you will need will be in that struct instance. |
| 09-11-2008, 04:34 AM | #10 |
Wouldn't just be easier to assign a struct per unit (Like Zerzax)? Then reset the necessary variables it if the spell has already affected the unit? So you would group the units in the AoE then loop through the units assign the struct if they don't have one and chuck them in a global group. If the units are in that global group when the spell is cast again array search up... then like I stated before change the necessary variables. And when the buff or whatever finishes just remove them from that global group -Av3n |
| 09-11-2008, 05:06 AM | #11 | |
Quote:
Then, at the end of any cast of the spell, the original owner is preserved. |
| 09-11-2008, 09:17 AM | #12 |
Well, the best way to implement it can in that case vary a lot depending on how exactly he wants the spell to work, so I guess he'd first have to explain that in more detail. Is it a one-time-cast buf spell, a cloud-type channeling spell or what? |
| 09-11-2008, 10:04 AM | #13 |
No channel spells, Moyack is angry at me because he says I only do channel spells (lol). The spells has no conflicts in his logic afaik, I am using the fact that 2 things don't happen exactly at the same time (thread stuff). Don't worry guys, I will very soon post the code here, once I finish the player thing, and you'll all be able to see it. |
| 09-11-2008, 12:06 PM | #14 | |
Quote:
In this case UnitA gets control of unit, and then UnitB (level 1) gets control right after right ? Well, if, so, UnitB will control the first 20 seconds, then UnitA will control the 40 seconds after, and then the poor guy will return to his owner, if I am not mistaken. Anyway, many people need to know what this spell is, so here it is. The spell is AOE instant. The target units don't get any buff, although I could add one, the whole thing is triggered. Here is the code I made so far. If you have any CONSTRUCTIVE criticism or suggestion that you think can help me solve the players problem, or improve the code, go ahead. JASS://=========================================================================== //A spell that selects all units inside the target AOE and confuses them, //changing their owner by an amount of time. // //Requires TimerUtils // //@author Flame_Phoenix // //@credits //- Rafael Br, the original creator of the spell and idea //- Anitarf, the guy with ideas about how to solve problems //- My first teacher of vJASS: Blue_Jeans //- All other people I forgot or ignored // //@version 1.0 //=========================================================================== scope Confusion initializer Init //This will be needed for spell's core, don't change private keyword tmpPlayer private keyword PlayerArray private keyword playerLevelChances //=========================================================================== //=============================SETUP START=================================== //=========================================================================== globals private constant integer AID = 'A003' //the rawcode of the ability private constant integer ARRAY_SIZE = 15 //the maximum number of players private constant integer MAX_LEVELS = 3 endglobals private constant function Duration takes integer level returns real return 20. + (level * 10) //the duration of the spell on the units endfunction private constant function Radius takes integer level returns real return 125. + (level * 75) //the radius the spell will have endfunction private function PlayersCallibration takes nothing returns nothing local integer i local integer j //these are all human players the game has set i = 0 loop exitwhen(i == 11) set PlayerArray[i] = Player(i) set i = i + 1 endloop //Neutral Computer controlled players set PlayerArray[12] = Player(PLAYER_NEUTRAL_AGGRESSIVE) set PlayerArray[13] = Player(PLAYER_NEUTRAL_PASSIVE) set PlayerArray[14] = Player(bj_PLAYER_NEUTRAL_VICTIM) //now we set the chances for all our human players for all levels //here, each human player has a 6.66% chance of controling the unit set i = 0 loop exitwhen( i == 3) set j = 0 loop exitwhen(j == 11) set playerLevelChances[i][j] = .666 set j = j + 1 endloop set i = i + 1 endloop //if you prefer, you can avoid loops and set the levels and chances //manually, like I do in this example set playerLevelChances[1][12] = .67 set playerLevelChances[1][13] = .67 set playerLevelChances[1][14] = .668 set playerLevelChances[2][12] = .67 set playerLevelChances[2][13] = .67 set playerLevelChances[2][14] = .668 set playerLevelChances[3][12] = .67 set playerLevelChances[3][13] = .67 set playerLevelChances[3][14] = .668 //PS: Note that this takes a lot more text however xD endfunction private function Targets takes nothing returns boolean //the units that will be affected by the spell return IsUnitEnemy(GetFilterUnit(), tmpPlayer) endfunction //=========================================================================== //=============================SETUP END===================================== //=========================================================================== //small array type playerChances extends real array[ARRAY_SIZE] globals //BIG array private playerChances array playerLevelChances[MAX_LEVELS] private player array PlayerArray[15] private group g private boolexpr b private player tmpPlayer endglobals //=========================================================================== private struct MyStruct unit caster integer level timer dur group array allPlayers[ARRAY_SIZE] static method create takes unit caster returns MyStruct local MyStruct data = MyStruct.allocate() local integer i //setting variables set data.caster = caster set data.level = GetUnitAbilityLevel(caster, AID) set data.dur = NewTimer() set i = 0 loop exitwhen (i == ARRAY_SIZE) set data.allPlayers[i] = CreateGroup() set i = i + 1 endloop return data endmethod method onDestroy takes nothing returns nothing local integer i = 0 loop exitwhen (i == ARRAY_SIZE) call DestroyGroup(.allPlayers[i]) set i = i + 1 endloop call ReleaseTimer(.dur) endmethod endstruct //=========================================================================== private function EndEffect takes nothing returns nothing //here we catch the timer local MyStruct data = MyStruct(GetTimerData(GetExpiredTimer())) local unit f local integer i //here we walk trhough the group array set i = 0 loop exitwhen(i == ARRAY_SIZE) //here we walk through every single unit inside the group loop set f = FirstOfGroup(data.allPlayers[i]) exitwhen(f == null) call GroupRemoveUnit(data.allPlayers[i], f) call SetUnitOwner(f, Player(i), true) endloop set i = i + 1 endloop call data.destroy() endfunction //=========================================================================== private function Conditions takes nothing returns boolean return GetSpellAbilityId() == AID endfunction //=========================================================================== private function Actions takes nothing returns nothing local MyStruct data = MyStruct.create(GetTriggerUnit()) local location spellLoc = GetSpellTargetLoc() local real spellX = GetLocationX(spellLoc) local real spellY = GetLocationY(spellLoc) local unit f //here we select the units we will affect set tmpPlayer = GetOwningPlayer(data.caster) call GroupEnumUnitsInRange(g, spellX, spellY, Radius(data.level), b) //and now we change their owners loop set f = FirstOfGroup(g) exitwhen(f == null) call GroupRemoveUnit(g, f) call GroupAddUnit(data.allPlayers[GetPlayerId(GetOwningPlayer(f))], f) //Problem, how do I change the players here? //how do I make it random ? call SetUnitOwner(f, Player(3), true) endloop //start the timer call SetTimerData(data.dur, integer(data)) call TimerStart(data.dur, Duration(data.level), true, function EndEffect) call RemoveLocation(spellLoc) set spellLoc = null endfunction //=========================================================================== private function Init takes nothing returns nothing local integer i local trigger ConfusionTrg = CreateTrigger( ) call TriggerRegisterAnyUnitEventBJ(ConfusionTrg, EVENT_PLAYER_UNIT_SPELL_EFFECT ) call TriggerAddCondition(ConfusionTrg, Condition( function Conditions)) call TriggerAddAction(ConfusionTrg, function Actions ) set ConfusionTrg = null //setting globals set g = CreateGroup() set b = Condition(function Targets) //calling functions call PlayersCallibration() //setting out globals array set i = 0 loop exitwhen(i == MAX_LEVELS) set playerLevelChances[i] = playerChances.create() set i = i + 1 endloop endfunction endscope I wish there could be something like a "Players" pool, it would really make my life easier, but since I am using dynamic arrays, there may be a better way out, I hope. |
| 09-11-2008, 08:38 PM | #15 | |
Quote:
EDIT EDIT EDIT Ok guys, since no one answers, I decided to try fixing it myself. I managed to do some loop and if stuff, but is is bugged, it always goes for the last player. Can some one please help me fix this ? Oh, btw, can some mod also change the title to [OLY]Confusion ?? JASS://=========================================================================== //A spell that selects all units inside the target AOE and confuses them, //changing their owner by an amount of time. // //Requires TimerUtils // //@author Flame_Phoenix // //@credits //- Rafael Br, the original creator of the spell and idea //- Anitarf, the guy with ideas about how to solve problems //- My first teacher of vJASS: Blue_Jeans //- All other people I forgot or ignored // //@version 1.0 //=========================================================================== scope Confusion initializer Init //This will be needed for spell's core, don't change private keyword tmpPlayer private keyword PlayerArray private keyword playerLevelChances //=========================================================================== //=============================SETUP START=================================== //=========================================================================== globals private constant integer AID = 'A003' //the rawcode of the ability private constant integer ARRAY_SIZE = 15 //the maximum number of players private constant integer MAX_LEVELS = 3 endglobals private constant function Duration takes integer level returns real return 20. + (level * 10) //the duration of the spell on the units endfunction private constant function Radius takes integer level returns real return 125. + (level * 75) //the radius the spell will have endfunction private function PlayersCallibration takes nothing returns nothing local integer i local integer j //these are all human players the game has set i = 0 loop exitwhen(i == 11) set PlayerArray[i] = Player(i) set i = i + 1 endloop //Neutral Computer controlled players set PlayerArray[12] = Player(PLAYER_NEUTRAL_AGGRESSIVE) set PlayerArray[13] = Player(PLAYER_NEUTRAL_PASSIVE) set PlayerArray[14] = Player(bj_PLAYER_NEUTRAL_VICTIM) //now we set the chances for all our human players for all levels //here, each human player has a 6.66% chance of controling the unit set i = 0 loop exitwhen( i == 3) set j = 0 loop exitwhen(j == 11) set playerLevelChances[i][j] = .666 set j = j + 1 endloop set i = i + 1 endloop //if you prefer, you can avoid loops and set the levels and chances //manually, like I do in this example set playerLevelChances[1][12] = .67 set playerLevelChances[1][13] = .67 set playerLevelChances[1][14] = .668 set playerLevelChances[2][12] = .67 set playerLevelChances[2][13] = .67 set playerLevelChances[2][14] = .668 set playerLevelChances[3][12] = .67 set playerLevelChances[3][13] = .67 set playerLevelChances[3][14] = .668 //PS: Note that this takes a lot more text however xD endfunction private function Targets takes nothing returns boolean //the units that will be affected by the spell return IsUnitEnemy(GetFilterUnit(), tmpPlayer) endfunction //=========================================================================== //=============================SETUP END===================================== //=========================================================================== //small array type playerChances extends real array[ARRAY_SIZE] globals //BIG array private playerChances array playerLevelChances[MAX_LEVELS] private player array PlayerArray[15] private group g private boolexpr b private player tmpPlayer endglobals //=========================================================================== private struct MyStruct unit caster integer level timer dur group array allPlayers[ARRAY_SIZE] static method create takes unit caster returns MyStruct local MyStruct data = MyStruct.allocate() local integer i //setting variables set data.caster = caster set data.level = GetUnitAbilityLevel(caster, AID) set data.dur = NewTimer() set i = 0 loop exitwhen (i == ARRAY_SIZE) set data.allPlayers[i] = CreateGroup() set i = i + 1 endloop return data endmethod method onDestroy takes nothing returns nothing local integer i = 0 loop exitwhen (i == ARRAY_SIZE) call DestroyGroup(.allPlayers[i]) set i = i + 1 endloop call ReleaseTimer(.dur) endmethod endstruct //=========================================================================== private function EndEffect takes nothing returns nothing //here we catch the timer local MyStruct data = MyStruct(GetTimerData(GetExpiredTimer())) local unit f local integer i //here we walk trhough the group array set i = 0 loop exitwhen(i == ARRAY_SIZE) //here we walk through every single unit inside the group loop set f = FirstOfGroup(data.allPlayers[i]) exitwhen(f == null) call GroupRemoveUnit(data.allPlayers[i], f) call SetUnitOwner(f, Player(i), true) endloop set i = i + 1 endloop call data.destroy() endfunction //=========================================================================== private function Conditions takes nothing returns boolean return GetSpellAbilityId() == AID endfunction //=========================================================================== private function Actions takes nothing returns nothing local MyStruct data = MyStruct.create(GetTriggerUnit()) local location spellLoc = GetSpellTargetLoc() local real spellX = GetLocationX(spellLoc) local real spellY = GetLocationY(spellLoc) local unit f local real chance local integer i //here we select the units we will affect set tmpPlayer = GetOwningPlayer(data.caster) call GroupEnumUnitsInRange(g, spellX, spellY, Radius(data.level), b) //and now we change their owners loop set f = FirstOfGroup(g) exitwhen(f == null) call GroupRemoveUnit(g, f) call GroupAddUnit(data.allPlayers[GetPlayerId(GetOwningPlayer(f))], f) set chance = GetRandomReal(0, 1) //if chance is lower than the first case, than we must treat it in special way if chance <= playerLevelChances[data.level][0] then call SetUnitOwner(f, Player(0), true) //this is for the middle cases elseif (chance > playerLevelChances[data.level][0]) and (chance <= playerLevelChances[data.level][ARRAY_SIZE - 1]) then set i = 1 loop exitwhen (i == ARRAY_SIZE - 1) if (chance > playerLevelChances[data.level][i]) and (chance <= playerLevelChances[data.level][i + 1]) then call SetUnitOwner(f, Player(i), true) endif set i = i + 1 endloop //and now for the last case elseif (chance > playerLevelChances[data.level][ARRAY_SIZE - 1]) then call SetUnitOwner(f, Player(bj_PLAYER_NEUTRAL_VICTIM), true) endif endloop //start the timer call SetTimerData(data.dur, integer(data)) call TimerStart(data.dur, Duration(data.level), true, function EndEffect) call RemoveLocation(spellLoc) set spellLoc = null endfunction //=========================================================================== private function Init takes nothing returns nothing local integer i local trigger ConfusionTrg = CreateTrigger( ) call TriggerRegisterAnyUnitEventBJ(ConfusionTrg, EVENT_PLAYER_UNIT_SPELL_EFFECT ) call TriggerAddCondition(ConfusionTrg, Condition( function Conditions)) call TriggerAddAction(ConfusionTrg, function Actions ) set ConfusionTrg = null //setting globals set g = CreateGroup() set b = Condition(function Targets) //calling functions call PlayersCallibration() //setting out globals array set i = 0 loop exitwhen(i == MAX_LEVELS) set playerLevelChances[i] = playerChances.create() set i = i + 1 endloop endfunction endscope |
