Posté le: 11/12/09 12:10 Sujet du message: Joueurs déconnectés
Hello,
Histoire de reprendre les bonnes habitudes: a priori Stars a encore un bug majeur: les joueurs sont souvent déconnectés en cours de partie.
Problème:
-Pas de message d'erreur fatal
-Pas de désynchronisation détectée
-Pas de Freeze de Warcraft ou autre. Simplement comme si ils perdaient la connexion.
Or, pourtant, il semble bel et bien que cela vienne de la carte.
Comment identifier le problème? Là je suis un peu à court d'idées.
Oui, d'une certaine manière; à la création des joueurs sur la carte, ça donne ça:
Secret:
Jass:
local integer i = 0
local timer t = NewTimer()
call EnableTrigger(TrigLeave)
call SetFloatGameState(GAME_STATE_TIME_OF_DAY,12.00)
call SetTimeOfDayScale(0.)
call SuspendTimeOfDay(true)
call FogModifierStart(CreateFogModifierRect(Player(PLAYER_NEUTRAL_AGGRESSIVE), FOG_OF_WAR_VISIBLE, bj_mapInitialPlayableArea, true, false))
call TimerStart(t, 3600.00, false, function RunBlackHole )
set BlackHoleTimerWindow = CreateTimerDialog(t)
call TimerDialogSetTitle(BlackHoleTimerWindow,"Anomaly Stabilisation")
call TimerDialogDisplay(BlackHoleTimerWindow, true)
loop
exitwhen i > 8
if GetPlayerSlotState(Player(i)) == PLAYER_SLOT_STATE_PLAYING then
call SetPlayerAbilityAvailable(Player(i),'A01N',false)//hyp spellbook
call SetPlayerAbilityAvailable(Player(i),'A02D',false)//shrapnel spellbook
call SetPlayerAbilityAvailable(Player(i),'A02V',false)//Steal spellbook
call SetPlayerAbilityAvailable(Player(i),'A02X',false)//Selfdestruction spellbooks
call SetPlayerAbilityAvailable(Player(i),'A02Y',false)//Selfdestruction spellbooks
call SetPlayerTechResearched(Player(i),CARGOSLOT,1)//Grants the first level of cargo slots
call SetResource(Player(i),500,50)//Resources
call SetPlayerTechMaxAllowed(Player(i),'h00O',1)//1 freeport max
call SetPlayerTechMaxAllowed(Player(i),'h01I',1)//Max nexus center: 1
call SetPlayerTechMaxAllowed(Player(i),'h006',0)//Max AA turret: 0
call SetPlayerTechMaxAllowed(Player(i),'h004',0)//Max dock mk I: 0
call SetPlayerTechMaxAllowed(Player(i),'h007',0)//Max ion canon: 0
call SetPlayerTechMaxAllowed(Player(i),'h00F',0)//Max warehouse: 0
call SetPlayerTechMaxAllowed(Player(i),'h003',0)//Base
call SetPlayerTechMaxAllowed(Player(i),'h01A',0)//Energy center
call SetPlayerTechMaxAllowed(Player(i),'h014',0)//Structure center
call SetPlayerTechMaxAllowed(Player(i),'h019',0)//Weapon center
call SetPlayerTechMaxAllowed(Player(i),'h01B',0)//production center
call SetPlayerTechMaxAllowed(Player(i),'h002',0)//Shipyard Mark I
call SetPlayerTechMaxAllowed(Player(i),'h011',0)//Shipyard Mark II
call SetPlayerTechMaxAllowed(Player(i),'h012',0)//Shipyard Mark II
call SetPlayerTechMaxAllowed(Player(i),'h001',0)//Station
call SetPlayerTechMaxAllowed(Player(i),'h005',0)//Torp Launcher
call SetPlayerTechMaxAllowed(Player(i),'h00Z',0)//Training Center
call SetPlayerTechMaxAllowed(Player(i),'h010',0)//Turret Base
set TmpX = GetStartLocationX(GetPlayerStartLocation(Player(i)))
set TmpY = GetStartLocationY(GetPlayerStartLocation(Player(i)))
set TmpAngle = GetRandomReal(0.,360.)
set TmpUnit= CreateUnit(Player(i),'h00M',TmpX+1000.*Cos(TmpAngle),TmpY+1000.*Sin(TmpAngle),0.)
call UnitAddAbility(TmpUnit,'A007')
set FirstShip[i]=TmpUnit
if Player(i)==GetLocalPlayer() then
call ClearSelection()
call SelectUnit(TmpUnit,true)
endif
set RankDummy[i]=CreateUnit(Player(i),RANKDUMMYID,0.,0.,0.)
set TmpDummy= CreateUnit(Player(i),'o00L',TmpX+1000.*Cos(TmpAngle),TmpY+1000.*Sin(TmpAngle),0.)
call UnitApplyTimedLife(TmpDummy,'BTLF',5.)
call IssueTargetOrder(TmpDummy,"innerfire", TmpUnit)
call IssueTargetOrder(TmpDummy,"bloodlust", TmpUnit)
call IssueImmediateOrder(TmpUnit,"divineshield")
if GetLocalPlayer() == Player(i) then
call PanCameraToTimed(TmpX+1000.*Cos(TmpAngle),TmpY+1000.*Sin(TmpAngle),0.)
endif
call SetPlayerAllianceStateBJ( Player(0), Player(i), bj_ALLIANCE_UNALLIED )
call SetPlayerAllianceStateBJ( Player(1), Player(i), bj_ALLIANCE_UNALLIED )
call SetPlayerAllianceStateBJ( Player(2), Player(i), bj_ALLIANCE_UNALLIED )
call SetPlayerAllianceStateBJ( Player(3), Player(i), bj_ALLIANCE_UNALLIED )
call SetPlayerAllianceStateBJ( Player(4), Player(i), bj_ALLIANCE_UNALLIED )
call SetPlayerAllianceStateBJ( Player(5), Player(i), bj_ALLIANCE_UNALLIED )
call SetPlayerAllianceStateBJ( Player(6), Player(i), bj_ALLIANCE_UNALLIED )
call SetPlayerAllianceStateBJ( Player(7), Player(i), bj_ALLIANCE_UNALLIED )
call SetPlayerAllianceStateBJ( Player(8), Player(i), bj_ALLIANCE_UNALLIED )
call SetPlayerAllianceStateBJ( Player(9), Player(i), bj_ALLIANCE_UNALLIED )
call SetPlayerAllianceStateBJ( Player(10), Player(i), bj_ALLIANCE_UNALLIED )
call SetPlayerAllianceStateBJ( Player(11), Player(i), bj_ALLIANCE_UNALLIED )
call Clear(i,"Choose a way", null,0 )
call AddButton(i,"Merchant", SetMerchant, 1, null, i)
call AddButton(i,"Military", SetMilitary, 2, null, i)
call AddButton(i,"Pirate", SetPirate, 3, null, i)
call AddButton(i,"Terrorist", SetTerrorist, 4, null, i)
call Show(i)
call Mb(board).AddPlayer(i)
endif
set i = i + 1
endloop
Au milieu du script, on voit la ligne suivante, donc dans le If then Else
Jass:
if GetLocalPlayer() == Player(i) then
call PanCameraToTimed(TmpX+1000.*Cos(TmpAngle),TmpY+1000.*Sin(TmpAngle),0.)
endif
Ca n'a lieu qu'au tout début de la partie, hors les déconnections sont en cours de jeu.
Sinon j'ai un déclencheur qui permet de régler la hauteur caméra:
Secret:
Jass:
scope hcam initializer init
//=================================================
globals
private constant string COM = "-cam"
endglobals
//=================================================
private function Conditions takes nothing returns boolean
set TmpPlayer = GetTriggerPlayer()
set TmpString = GetEventPlayerChatString()
set TmpReal = S2R(SubString(TmpString, 5, 9))
if TmpReal > 199 and TmpReal < 4001 then
if TmpPlayer == GetLocalPlayer() then
call SetCameraField(CAMERA_FIELD_TARGET_DISTANCE, TmpReal, 1.00)
endif
else
call ErrorSound(TmpPlayer)
call DisplayTextToPlayer(TmpPlayer,0.,0.,"Camera argument must be between 200 and 4000")
endif
return false
endfunction
//=================================================
public function init takes nothing returns nothing
local trigger t = CreateTrigger()
local integer i = 0
loop
exitwhen i > 9
call TriggerRegisterPlayerChatEvent( t, Player(i), COM, false )
set i = i + 1
endloop
call TriggerAddCondition(t, Condition(function Conditions))
endfunction
//=================================================
endscope
Y'a bien une fonction caméra dans un if then else.
Wait for sound; pas à ma connaissance, j'utilise SoundsUtils comme librairie, voici le code.
Secret:
Jass:
library SoundUtils requires Stack, TimerUtils
//******************************************************************************
//* BY: Rising_Dusk
//*
//* Sounds are a very picky datatype in WC3. They have many quirks that one must
//* account for in order to use them, and simply using the internal WE Sound
//* Editor isn't enough because the sounds it makes can't be played multiple
//* times at once. 3-D sounds are also very tricky because there are different
//* WC3 sound options that a user can have activated where certain sounds will
//* or will not work. This library attempts to streamline the handling of sounds
//* so that it is less likely to confuse you or cause problems.
//*
//* The .mp3 format can be used for 3-D sounds, but there is one problem that
//* must be noted. If your computer supports the "Dolby Surround" sound option
//* in WC3 and you have it selected, then .mp3 files will work for 3-D sounds.
//* If you don't, however, they may not work depending on what you do have
//* selected and what is available for your computer. The .wav format works on
//* all possible settings, making them excellent for general use. This library
//* can interface with sounds of either type.
//*
//* Known issues with sounds that this library resolves:
//* - A given sound variable can only be played once at a time. In order to
//* play a sound type multiple times at once, you need multiple variables.
//* - A sound cannot be played at the same instant that it is created.
//*
//* The DefineSound function defines a sound type based on some basic parameters
//* the user provides. DefineSoundEx is available if the user wants control over
//* all possible parameters, though they won't have an impact most of the time.
//* The duration parameter for DefineSound and DefineSoundEx is in milliseconds,
//* which is consistent with Blizzard's natives. To get the duration of a given
//* sound, open up the WE's Sound Editor, navigate to your sound, and select
//* "Add as Sound." In doing so, it will show its duration in seconds. Multiply
//* that number by 1000 and use it as the duration argument.
//*
//* This library returns a sound variable with RunSound that you can change the
//* settings of using the standard JASS sound API. The library assigns default
//* values to the parameters for 2-D and 3-D sounds, that way they will run
//* without any further help.
//*
//* The library automatically allocates, runs, and recycles a sound when you
//* call RunSound. This library will not automatically recycle looping sounds,
//* so you will need to call ReleaseSound on the looping sound when you want it
//* to end.
//*
//******************************************************************************
//*
//* > function DefineSound takes string fileName, integer duration, ...
//* boolean looping, boolean is3D returns integer
//*
//* This function defines a sound type with a short list of parameters. The
//* returned integer serves as a SOUND_TYPE for running this type of sound at
//* any other point in a map.
//*
//* > function DefineSoundEx takes string fileName, integer duration, ...
//* boolean looping, boolean is3D, boolean stopwhenoutofrange, ...
//* integer fadeInRate, integer fadeOutRate, string eaxSetting ...
//* returns integer
//*
//* This function serves an identical purpose to DefineSound, but gives the user
//* full control over the entire list of parameters. Similar to DefineSound, the
//* returned integer serves as a SOUND_TYPE for running this type of sound.
//*
//* > function RunSound takes integer soundRef returns sound
//*
//* This function runs a sound with the parameters held within the soundRef
//* integer argument. The soundRef argument is the returned value of DefineSound
//* or DefineSoundEx.
//*
//* > function RunSoundOnUnit takes integer soundRef, unit whichUnit returns sound
//*
//* The same as RunSound, just this function runs a sound of a given type on a
//* specified unit.
//*
//* > function RunSoundAtPoint takes integer soundRef, real x, real y, real z returns sound
//*
//* The same as RunSound, just this function runs a sound of a given type at a
//* specified point in 3D space.
//*
//* > function RunSoundForPlayer takes integer soundRef, player p returns sound
//*
//* The same as RunSound, just this function runs a sound of a given type only
//* for the specified player.
//*
//* > function ReleaseSound takes sound s returns boolean
//*
//* This function need only be called on looping sounds. If a sound is not
//* looping, it will be released and recycled on its own. This function should
//* be used on looping sounds when you want them to end.
//*
//* Example usage:
//* set SOUND_TYPE = DefineSound("Sound\\Path.wav", 300, false, true)
//* call RunSound(SOUND_TYPE)
//* call RunSoundOnUnit(SOUND_TYPE, SomeUnit)
//* call RunSoundAtPoint(SOUND_TYPE, x, y, z)
//* call RunSoundForPlayer(SOUND_TYPE, Player(5))
//* call ReleaseSound(SomeLoopingSound)
//*
globals
private hashtable ht = InitHashtable() //Attach sound types to sounds
private hashtable st = InitHashtable() //Sound hashtable
private hashtable rt = InitHashtable() //Attach soundrecyclers to sounds
private hashtable kt = InitHashtable() //Attach StopSound data
endglobals
//Struct for each sound type
private struct soundhelper
//Stack associated to each struct
Stack sta
static method create takes string fileName, integer duration, boolean looping, boolean is3D, boolean stopwhenoutofrange, integer fadeInRate, integer fadeOutRate, string eaxSetting returns soundhelper
local soundhelper sh = soundhelper.allocate()
//Load the parameters so the sound can be created later as necessary
set sh.fileName = fileName
set sh.duration = duration
set sh.looping = looping
set sh.is3D = is3D
set sh.stopwhenoutofrange = stopwhenoutofrange
set sh.fadeInRate = fadeInRate
set sh.fadeOutRate = fadeOutRate
set sh.eaxSetting = eaxSetting
//Create the stack for the struct
set sh.sta = Stack.create()
return sh
endmethod
endstruct
//Struct for holding data for the sound recycling
private struct soundrecycler
timer t = null
sound s = null
integer sh = 0
boolean stopped = false //Only gets used if StopSound is called on a new sound
static method create takes sound whichSound, integer soundRef returns soundrecycler
local soundrecycler sr = soundrecycler.allocate()
set sr.t = NewTimer()
set sr.s = whichSound
set sr.sh = soundRef
call SetTimerData(sr.t, integer(sr))
//Hook the value to the soundRef and whichSound
call SaveInteger(rt, soundRef, GetHandleId(whichSound), integer(sr))
return sr
endmethod
private method onDestroy takes nothing returns nothing
call RemoveSavedInteger(rt, .sh, GetHandleId(.s))
call ReleaseTimer(.t)
endmethod
endstruct
private function HookStopSound takes sound soundHandle, boolean killWhenDone, boolean fadeOut returns nothing
local integer id = GetHandleId(soundHandle)
local integer soundRef = 0
local soundrecycler sr = 0
if HaveSavedInteger(ht, 0, id) then //Sound is from stacks
set soundRef = LoadInteger(ht, 0, id)
if HaveSavedInteger(rt, soundRef, id) then //Sound has a recycler
set sr = soundrecycler(LoadInteger(rt, soundRef, id))
set sr.stopped = true
endif
if killWhenDone then
debug call BJDebugMsg(SCOPE_PREFIX+"Warning: (StopSound) Destroying a sound in the stack")
endif
endif
endfunction
hook StopSound HookStopSound
private function HookKillSoundWhenDone takes sound soundHandle returns nothing
if HaveSavedInteger(ht, 0, GetHandleId(soundHandle)) then
call BJDebugMsg(SCOPE_PREFIX+"Warning: (KillSoundWhenDone) Destroying a sound in the stack")
endif
endfunction
function ReleaseSound takes sound s returns boolean
local integer id = GetHandleId(s)
local integer soundRef = 0
local soundhelper sh = 0
local soundrecycler sr = 0
if s == null then
debug call BJDebugMsg(SCOPE_PREFIX+"Error: Cannot recycle a null sound")
return false
elseif not HaveSavedInteger(ht, 0, id) then
debug call BJDebugMsg(SCOPE_PREFIX+"Error: Cannot recycle a sound not allocated by RunSound")
return false
endif
set soundRef = LoadInteger(ht, 0, id)
set sh = soundhelper(soundRef)
call StopSound(s, false, true) //Stop the sound
call sh.sta.push(id) //Return it to the stack
call SaveSoundHandle(st, soundRef, id, s) //Save it to hashtable
if not sh.looping then
//soundrecycler only exists for non-looping sounds
set sr = soundrecycler(LoadInteger(rt, soundRef, id))
call sr.destroy() //Destroy recycler helper
endif
return true
endfunction
private function Recycle takes nothing returns nothing
local soundrecycler sr = soundrecycler(GetTimerData(GetExpiredTimer()))
local soundhelper sh = soundhelper(sr.sh)
local integer id = GetHandleId(sr.s)
call StopSound(sr.s, false, true) //Stop the sound
call sh.sta.push(id) //Return it to the stack
call SaveSoundHandle(st, integer(sh), id, sr.s) //Save it to hashtable
call sr.destroy() //Destroy recycler helper
endfunction
private function Run takes nothing returns nothing
local soundrecycler sr = soundrecycler(GetTimerData(GetExpiredTimer()))
local soundhelper sh = soundhelper(sr.sh)
if not sr.stopped then
call StartSound(sr.s) //Play sound here
endif
if not sh.looping and not sr.stopped then
call TimerStart(sr.t, sh.duration*0.001, false, function Recycle)
else
call sr.destroy()
endif
endfunction
function RunSound takes integer soundRef returns sound
local sound s = null
local integer i = 0
local soundhelper sh = soundhelper(soundRef)
local soundrecycler sr = 0
if soundRef <= 0 then
debug call BJDebugMsg(SCOPE_PREFIX+"Error: Cannot run sound of undefined type")
return null
endif
//Check if the stack is empty
if sh.sta.peek() == Stack.EMPTY then
//Create a new sound for the stack
set s = CreateSound(sh.fileName, sh.looping, sh.is3D, sh.stopwhenoutofrange, sh.fadeInRate, sh.fadeOutRate, sh.eaxSetting)
//Attach the type to the sound for future reference
call SaveInteger(ht, 0, GetHandleId(s), integer(sh))
call SetSoundDuration(s, sh.duration)
//Stuff that must be performed immediately upon creation of sounds
call SetSoundChannel(s, 5)
call SetSoundVolume(s, 127)
call SetSoundPitch(s, 1.)
if sh.is3D then
//These are settings necessary for 3-D sounds to function properly
//You can change them at will outside of this function
call SetSoundDistances(s, 600., 10000.)
call SetSoundDistanceCutoff(s, 3000.)
call SetSoundConeAngles(s, 0., 0., 127)
call SetSoundConeOrientation(s, 0., 0., 0.)
endif
//Start sound after a delay because it was created here
set sr = soundrecycler.create(s, soundRef)
call TimerStart(sr.t, 0.001, false, function Run)
else
//Allocate a sound from the stack
set i = sh.sta.pop()
if not HaveSavedHandle(st, soundRef, i) then
debug call BJDebugMsg(SCOPE_PREFIX+"Error: No sound in given stack member")
return null
endif
set s = LoadSoundHandle(st, soundRef, i)
call RemoveSavedInteger(st, soundRef, i)
call SetSoundVolume(s, 127) //Start volume at max
//Start it here since it wasn't created here
call StartSound(s)
//Recycle the sound in a timer callback after it's finished if nonlooping
if not sh.looping then
set sr = soundrecycler.create(s, soundRef)
call TimerStart(sr.t, sh.duration*0.001, false, function Recycle)
endif
endif
return s
endfunction
function RunSoundOnUnit takes integer soundRef, unit whichUnit returns sound
local sound s = RunSound(soundRef)
call AttachSoundToUnit(s, whichUnit)
return s
endfunction
function RunSoundAtPoint takes integer soundRef, real x, real y, real z returns sound
local sound s = RunSound(soundRef)
call SetSoundPosition(s, x, y, z)
return s
endfunction
function RunSoundForPlayer takes integer soundRef, player p returns sound
local sound s = RunSound(soundRef)
if GetLocalPlayer() != p then
call SetSoundVolume(s, 0)
else
call SetSoundVolume(s, 127)
endif
return s
endfunction
endlibrary
Inscrit le: 23 Aoû 2007 Messages: 7146 Sujets: 147 Spécialité en worldedit: le troll, le flood, la vulgarité, mon coeur balance Médailles: 2 (En savoir plus...)
Posté le: 11/12/09 18:18 Sujet du message:
Les mouvements X/Y de caméra ne sont pas appliqués sur les pc dont war3 est réduit (à ne pas confondre avec le mode fenêtre).
Et les sons ne sont non plus pas joués sur ces mêmes pc.
Donc si tu utilisais camera target X/Y, même si ces valeurs sont naturellement locales (propres à chaque joueur), avec des lock camera, ou autre, ces valeurs devraient être les même pour tous si on n'utilise pas ces fonctions avec GetLocalPlayer, en toute logique.
Mais comme je l'ai décrit, ce n'est pas forcément vrai.
Ça pourrait donc désynchroniser si tu ne connaissais pas cette particularité (ce que je présume).
Bien que je ne vois pas l'intérêt d'un tel if/then cependant.
Ça ne semble pas être ton cas toutefois, d'après les codes postés.
Utilise tu KillSoundWhenDone ?
Bien que je suppose que cela ne désynchroniserait pas. _________________
Ca pourrait donc désynchroniser si tu ne connaissais pas cette particularité (ce que je présume)
Exact Merci pour l'information
Troll-Brain a écrit:
Utilise tu KillSoundWhenDone ?
Bien que je suppose que cela ne désynchroniserait pas.
Non, les seuls sons que j'utilise sont grâce à SoundUtils, et je ne me sert que des fonctions de base (déclarer l'entier associé au son, puis jouer le son en utilisant les fonctions de cette librairies (genre RunSoundOnUnit(SOUND_MYSOUND,whichUnit)
Sur WC3Campaign Rising_Dusk me dit que si il n'y a pas de désync/d'erreur fatale c'est uniquement lié aux joueurs, à sa connaissance.
=>Il ne m'aide pas des masses. _________________
1-Les déclarations de déclencheurs
2-Les attributions de variables VJass globales
3-Les déclarations de la library SpellEvent (Exemple: call RegisterSpellCastResponse(L'Id du sort, la fonction associée) )
4-Les déclarations de la library AbilityPreload (call AbilityPreload (L'id du sort) )
5-Les déclarations de la library SoundsUtils ( call DefineSound(Chemin du fichier son, durée, se joue en boucle ou pas, est 3D ou pas) ).
Et c'est tout.
J'ai lancé la bêta 8 qui est bugguée à cause du système de boites de dialogues, donc injouable (je termine la beta9) mais le problème a lieu quand même: plusieurs joueurs sont systématiquement bloqués à 95% du chargement de la carte.
Je vais finir par croire que c'est le widgetizer ou l'optimizer qui ont un problème. Ca m'était arrivé avec les premières version de Stars, W3Optimizer n'utilisait pas toutes les natives IsUnitType() (UNIT_TYPE_TAUREN par exemple) à l'époque.
Je vais devoir tester en open source non optimisé tout ça cet après-midi. _________________
Page 1 sur 1 La question posée dans ce topic a été résolue !
Vous ne pouvez pas poster de nouveaux sujets dans ce forum Vous ne pouvez pas répondre aux sujets dans ce forum Vous ne pouvez pas éditer vos messages dans ce forum Vous ne pouvez pas supprimer vos messages dans ce forum Vous ne pouvez pas voter dans les sondages de ce forum