| 01-08-2008, 08:41 PM | #2 |
the timer Between_Levels_Timer can't expire more than each 9 s (0.3*30) ? |
| 01-08-2008, 11:00 PM | #3 |
hmmm do you have tested if threads still alive ? aka add some message on function end ? and yes begin... or you could make it internal. for example. timer executes function Code:
if not mybool then
set mybool=true
else
call echo("WTF !? Dead Thread walking TT") // it's a error message
endif
...
// bla bla your code
...
set mybool=false |
| 01-08-2008, 11:46 PM | #4 |
Please explain this: ConvertedPlayer( ( id / 2 ) + 9 )
Notice that ConvertedPlayer requires ids that begin with 1. There are a lot of things to fix in your code, but I need to understand that one before doing anything. Do you really intend it to require 13 seconds to generate all the units? |
| 01-09-2008, 12:23 AM | #5 | |
Quote:
I appreciate the response Vexorian (and others), and would be grateful for any fixes. There are 8 human players in the map. In order to reduce creep clumping during movement, the map was converted from 1 computer spawning player to 4. What this means, is that every two players gets a computer spawner. Thus, id/2 from 0-7 will generate a range from 0-3. Add 9 to that, and you get a range between 9-12. Players 9-12 are the computer spawners. |
| 01-09-2008, 12:32 AM | #6 |
id : 0-7 id/2 : 0-3 id/2 + 9 : 9-12 (id/2 +9) - 1 = 8-11 I think you are better adding by 8 and using Player() instead of ConvertedPlayer(), but it looks like the issue was not caused by this gonna take a further look. |
| 01-09-2008, 12:45 AM | #7 |
That part is irrelevant Vex. If I remember correctly it has something to do with assigning witch human player will get witch computer player to fight against. This is the source of problem: JASS://=========================================================================== function Start_Level_Spawns takes nothing returns nothing set udg_Spawn_Loop = udg_Spawn_Loop + 1 if udg_Spawn_Loop>31 then call PauseTimer(Tspawn) return endif set udg_Player_Group = GetPlayersMatching(Condition(function AlivePlayerFilter)) call ForForce( udg_Player_Group, function SpawnCreep ) call DestroyForce(udg_Player_Group) endfunction This function is periodically called, and in every periodic call it creates a force of all active players and spawns a creep for them. That whole force thing should be out of there, perhaps doing it at the beginning of each level. Maybe it is hitting the OP limit for some reason?? Ok so the above function is calling this for each player JASS://=========================================================================== function SpawnCreep takes nothing returns nothing local integer id = GetPlayerId(GetEnumPlayer()) local unit u local real hp if udg_Spawn_Loop > 0 then set udg_Temp_Point = GetRectCenter(udg_Region_Spawn[id]) set u = CreateUnitAtLoc(ConvertedPlayer( ( id / 2 ) + 9 ),udg_Spawns[udg_Level - 1],udg_Temp_Point,270.) call RemoveLocation(udg_Temp_Point) //call SetUnitUserData( u, GetConvertedPlayerId(GetEnumPlayer()) ) set udg_CreepOwner[GetUnitIndex(u)] = GetEnumPlayer() // <------<< call UnitAddAbility(u,udg_Spawn_HP[udg_Level - 1]) set hp = ((udg_Difficulty[id]-1)*.125)+.50 call SetWidgetLife(u,GetUnitState(u,UNIT_STATE_MAX_LIFE)*hp) set u = null endif endfunction the commented line above is how it used to be before. Now Karawasa once asked me if error might be happening because of PUI. I said no. If it was an error in PUI it would be reported by system itself. And as far as I know Karawasa did not report any PUI messages showing up. Karawasa? Anyways I just wanted to mention that in the unlikely case that I was wrong. My best bet for fixing the problem right now is putting those forces outside the loop and making udg_Spawn_Loop a private variable inside spawn scope so it is sure no other triggers are messing with it. EDIT: Important question: does spawning stop for ALL players or only for some players. If it is only some players the error is probably here: JASS://=========================================================================== function AlivePlayerFilter takes nothing returns boolean return ( udg_Player_Lives[GetPlayerId(GetFilterPlayer())] > 0 ) endfunction |
| 01-09-2008, 01:17 AM | #8 |
@Cohadar: No error messages for PUI come up. In regards to the bug itself, it stops spawning for ALL players. |
| 01-09-2008, 01:46 AM | #9 |
My guess is your problem is elsewhere, check all the points where you start udg_Between_Levels_Timer up because if you start it before it has spawned all 30 monsters you'd get the effect of only ... 20 of them spawning. Something similar... I looked over your code and there is no reason it wouldnt spawn all 30. |
| 01-09-2008, 02:45 AM | #11 |
I'm seeing some inconsistancies here. In Trigger Unit Dies you set Temp_Player = CreepOwner[(Custom value of (Dying unit))]. In the spawning function you set CreepOwner[GetUnitIndex(u)] = GetEnumPlayer(). Now heres the strange part. You never set the custom value of the unit when its spawned, is that set another time? Assuming it isn't, you'd essentially have 0 custom value for all units. GetUnitIndex() probably never returns 0, i don't know the specifics but my guess is 0 would mean error or null. So ALL checks in the Unit Dies trigger would have Temp_Player = CreepOwner[0] which is probably null. (Player number of NULL) - 1 is probably -1. Array access of -1 yields? Maybe I'm reading this wrong... EDIT: Found another issue: CreepFilter -- udg_CreepOwner[GetUnitUserData(GetFilterUnit())], GetUnitUserData should be GetUnitIndex no? If that returns 0 then udg_creepOwner is probably null, and (null == GetEnumPlayer()) == FALSE always, so you are essentially counting no units in CountCreeps function. Add 30 to that, you got yourself a mis-valued counter. It'll say theres 30 units left in the wave but really theres 36 because 6 of those units are still alive. My guess is your TD allows for multiple waves to coexist at the same time? (OK its not a guess I've played your TD before :P). If it says theres 30 but theres 36, then you may have a problem down the road. |
| 01-09-2008, 02:46 AM | #12 |
Try using a normal loop instead of ForForce (which nobody outside of GUI should use) When you do ForForce you rely unnecessarily on the handle stuff if you got a bug in your map that screws the handle ref counter then this problem could be a consequence. You can also just apply code reuse and fix the whole Ronalds stuff, you have extra code for that stuff when just using the normal spawn code + very few if then elses inside of it would work. Use debugging messages to verify that the timer itself runs 30 times |
| 01-09-2008, 03:53 AM | #13 |
@rain9441: I don't think either of those are an issue, as the above mentioned bug is the only problem I am having. If there was a problem with custom value, bounty and other functions would work incorrectly. If there was a problem with the count, then the next wave timer would sometimes not start. Neither of these happen. I really appreciate you looking through the code though. @Vexorian: Would you be kind enough to rewrite the code to reflect your changes? Do you have any other ideas? What do you think of Cohadar's idea? |
| 01-09-2008, 04:14 PM | #14 | |
Quote:
There are no inconsistencies regarding Custom Unit Data, GetUnitIndex is a function from PUI that automatically sets index for every unit, and since it is called for every unit after it is spawned there is no need to call it any more, you can use Custom Value Directly. The problem is not there. I tested the game (with debug messages) and it was all fine all 40 levels. I guess it only happens in multiplayer for some reason. The most probably reason is what Vex mentioned. Handle Stack Corruption Here is why I think so: I installed this trigger in EleTD: JASS:library HandleCounter globals private leaderboard Leaderboard = null private integer MaxHandleIndex = 0 private location loc string GAME_TIME_STRING = "Game Time: " // leaderboard dummy players private constant player LDP_TIME = Player(11) private constant player LDP_HNUM = Player(8) integer GAME_SECONDS = 0 integer GAME_MINUTES = 0 integer GAME_HOURS = 0 endglobals private function H2I takes handle h returns integer return h return 0 endfunction private function LeaderboardTimeTick takes nothing returns nothing call LeaderboardSetPlayerItemLabelBJ( LDP_TIME, Leaderboard, GAME_TIME_STRING + I2S(GAME_HOURS) + ":" + I2S(GAME_MINUTES)) call LeaderboardSetPlayerItemValueBJ( LDP_TIME, Leaderboard, GAME_SECONDS) endfunction private function Actions takes nothing returns nothing set Leaderboard = CreateLeaderboard() //call BJDebugMsg("Leaderboard Created") call LeaderboardSetLabel(Leaderboard, "") call ForceSetLeaderboardBJ(Leaderboard, bj_FORCE_ALL_PLAYERS) call LeaderboardAddItemBJ( LDP_TIME, Leaderboard, GAME_TIME_STRING , 0 ) call LeaderboardAddItemBJ( LDP_HNUM, Leaderboard, "Handle Count:", 0 ) call LeaderboardSetPlayerItemLabelColorBJ( LDP_TIME, Leaderboard, 0xFF, 0xCC, 0x00, 0 ) call LeaderboardSetPlayerItemValueColorBJ( LDP_TIME, Leaderboard, 0xFF, 0xCC, 0x00, 0 ) call LeaderboardSetPlayerItemLabelColorBJ( LDP_HNUM, Leaderboard, 0xCC, 0x00, 0xFF, 0 ) call LeaderboardSetPlayerItemValueColorBJ( LDP_HNUM, Leaderboard, 0xCC, 0x00, 0xFF, 0 ) call LeaderboardDisplay(Leaderboard, true) call LeaderboardResizeBJ(Leaderboard) endfunction //=========================================================================== private function UpdateHandleCount takes nothing returns nothing set loc = Location(0,0) set MaxHandleIndex = IMaxBJ(MaxHandleIndex, H2I(loc)-0x100000) call RemoveLocation(loc) call LeaderboardSetPlayerItemValueBJ( LDP_HNUM, Leaderboard, MaxHandleIndex ) endfunction //=========================================================================== private function Tick takes nothing returns boolean set GAME_SECONDS = GAME_SECONDS + 1 if GAME_SECONDS >= 60 then set GAME_SECONDS = 0 set GAME_MINUTES = GAME_MINUTES + 1 endif if GAME_MINUTES >= 60 then set GAME_MINUTES = 0 set GAME_HOURS = GAME_HOURS + 1 endif call LeaderboardTimeTick() return false endfunction //=========================================================================== public function InitTrig takes nothing returns nothing local trigger trig = CreateTrigger() call TriggerRegisterTimerEventSingle( trig, 0.00 ) call TriggerAddAction( trig, function Actions ) set trig = CreateTrigger() call TriggerRegisterTimerEventPeriodic( trig, 1.00 ) call TriggerAddCondition( trig, Condition(function Tick) ) set trig = CreateTrigger() call TriggerRegisterTimerEventPeriodic( trig, 1.00 ) call TriggerAddAction( trig, function UpdateHandleCount ) endfunction endlibrary What I discovered is that EleTD is leaking like 30 handles per second even when there is nothing happening on the map. Combined with overly optimistic use of gamecache == pwned (you can blame emjlr3 for that )------------------------------------------------------------------- Well Karawasa it basically comes to this: Looks like you will finally have to get off you lazy ass and learn some jass. Most importantly cleaning memory leaks and nulling locals. Otherwise EleTD is as good as dead. ------------------------------------------------------------------- |
| 01-09-2008, 07:53 PM | #15 |
feel free to change my GC usage to PUI, since that is all I use it for, in anycase, GC is not the reason this bugs, and don't even begin to think it is, hundreds of peple have used GC for many things in vrey big maps, including me, with no problems the bug is not reproducable, it haappens at random times in random games, and I nor Kara have been able to reproduce it in Single Player or Online as I have told Kara before, the only reasons this would bug is if the timer randomly stopped, cold(however, other triggers should reactivate it, as you have seen), if an OP limit is hit somewhere(again, other triggers should activate it), or if the ForForce somehow stopped in the middle I do not think the problem lies in this trigger, as I have said before, any thing botched in here, creeps would stop spawning in the middle of doing so, which does not happen (unless somehow the ForForce can bug and hit an OP limit or some shit, like I said)... I think it funny that at first all people looked at were things that in no way reflected this bug, only less then perfectly optimized coding, as if that were the cure to all the worlds problems... |
