Worldedit
  Worldedit
Le site sur l'éditeur de warcraft 3 !
 
  FAQFAQ   RechercherRechercher   Liste des MembresListe des Membres    Groupes d'utilisateursGroupes d'utilisateurs   medals.php?sid=50ee32a9a5e37529ddea375d34c31264Médailles   S'enregistrerS'enregistrer 
 ProfilProfil   Se connecter pour vérifier ses messages privésSe connecter pour vérifier ses messages privés   ConnexionConnexion 
  FAQFAQ World Editor   UploadUploader une map ou une image    UploadAjouter sa map à l'annuaire   UploadConsulter l'annuaire

Optimisation: Indepdant Summon

 
Poster un nouveau sujet   Répondre au sujet    Worldedit Index du Forum -> Aide sur les déclencheurs
Voir le sujet précédent :: Voir le sujet suivant  
Auteur Message
 jk2pach
Invité








MessagePosté le: 22/01/10 11:58    Sujet du message: Optimisation: Indepdant Summon Citer

Bon je crois que le plus simple est de faire trigger par trigger.

J'ai viré le I2Struct. Est-ce que c'est mieux maintenant?

Rappel: le système consiste à faire suivre une unité par une autre. Si la distance est faible, l'unité va défendre le maître. Si elle est importante, elle va rejoindre le maître. Si elle vraiment trop importante, elle téléporte l'unité vers le maître.
Jass:
library IndSum initializer init requires Table, TimerUtils, BoundSentinel,GroupUtils
//=================================================
globals
    private constant real TIMEOUT = 5.00
    private constant real COMETOMIN = 50.
    private constant real COMETOMAX = 200.
    private constant real DISMAX = 500.
    private constant real DISMAXTP = 2500.
    private constant string FX = "Abilities\\Spells\\NightElf\\Blink\\BlinkCaster.mdl"
endglobals
//=================================================
private keyword s_IndSum
globals
    private HandleTable TABLE
endglobals
//=================================================
private function init takes nothing returns nothing
    set TABLE = HandleTable.create()
endfunction
//=================================================
private function runtimerorder takes nothing returns nothing
local s_IndSum g = GetTimerData( GetExpiredTimer() )
    call g.UpdateOrder()
endfunction
//================================================= 
private struct s_IndSum
    private unit master
    private unit summon
    private timer ti = null
//=================================================
method UpdateOrder takes nothing returns nothing
local integer o=GetUnitCurrentOrder(.summon)
local real tx=GetUnitX(.master)
local real ty=GetUnitY(.master)
local real angle = 0.
local real dist = 0.

    if GetUnitState(.summon,UNIT_STATE_LIFE) > 0 then
        set dist=Pow(tx-GetUnitX(.summon),2) + Pow(ty-GetUnitY(.summon),2)
        if dist > DISMAX and dist<DISMAXTP  and (o == 0 or o == OrderId("attack") or o == OrderId("move") or o == OrderId("stop") or o==851971) then
            call IssuePointOrder(.summon, "move", tx,ty)
        else
            if dist >= COMETOMIN and (o == 0 or o == 851971) then
                set angle = GetRandomReal( GetUnitFacing(.master)-80, GetUnitFacing(.master)+80)
                if (ModuloInteger(GetUnitPointValue(.summon),2)==0) then
                    set angle=angle * bj_DEGTORAD
                else
                    set angle=- angle * bj_DEGTORAD
                endif
                set dist = GetRandomReal(COMETOMIN, COMETOMAX )
                set tx=tx+dist*Cos(angle)
                set ty=ty+dist*Sin(angle)
                if not IssuePointOrder(.summon, "attack", tx, ty ) then
                    call IssuePointOrder(.summon, "move", tx, ty )
                endif
            endif
        endif
        if dist>DISMAXTP then
            call DestroyEffect(AddSpecialEffect(FX,GetUnitX(.summon),GetUnitY(.summon)))
            call DestroyEffect(AddSpecialEffect(FX,tx,ty))
            call SetUnitPosition(.summon,tx,ty)
        endif
    else
        call .Release()
    endif
endmethod
//=================================================
method Link takes unit master returns nothing
    set .master = master
    set .ti = NewTimer()
    call SetTimerData( .ti, this )
    call TimerStart( .ti, TIMEOUT, true, function runtimerorder )
endmethod
//=================================================       
method Release takes nothing returns nothing
    call ReleaseTimer(.ti)
    set .ti = null
    set .master = null   
    call .destroy()
endmethod
//=================================================
//Constructor
static method create takes unit summon returns s_IndSum
local s_IndSum this = s_IndSum.allocate()
        set this.summon = summon
        return this
endmethod
//=================================================       
endstruct
//=================================================
function IndSum takes unit summon returns s_IndSum
    if( summon==null )then
        return 0
    endif
    if( not TABLE.exists(summon) )then
        set TABLE[summon] = s_IndSum.create(summon)
    else
        call TABLE.destroy((TABLE[summon]))
        set TABLE[summon] = s_IndSum.create(summon)
    endif
    return s_IndSum(TABLE[summon])
endfunction
endlibrary


Exemple d'appel:
Jass:
scope summonfighter initializer init
//=================================================
globals
    private constant string FX = "Abilities\\Spells\\Demon\\DarkPortal\\DarkPortalTarget.mdl"
endglobals
//=================================================
private function Conditions takes nothing returns boolean
local unit caster = GetSummoningUnit()
local unit drone = GetSummonedUnit()
local integer droneId = GetUnitTypeId(drone)
    if GetUnitTypeId(caster) == 'n005' and (droneId == 'h01F' or droneId == 'h01G') then
        call DestroyEffect(AddSpecialEffectTarget(FX,drone,"origin"))
        call IndSum(drone).Link(caster)
    endif
    set caster = null
    set drone = null
    return false
endfunction
//=================================================
public function init takes nothing returns nothing
local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SUMMON )
    call TriggerAddCondition(t, Condition(function Conditions))
endfunction   
//=================================================
endscope

_________________
Revenir en haut
 jk2pach
Invité








MessagePosté le: 12/02/10 21:52    Sujet du message: Citer

Réglé, j'utilise ça pour le moment:
Jass:
library IndieSummons initializer Init requires AutoIndex, TimerUtils, Table
//**************************************************************************************************
//*
//* Independant Summons (Code + config)
//* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//* You just need to copy this trigger, notice that these functions do nothing without the other
//* part which has the header functions and you'll also need to call them.
//*
//**************************************************************************************************

// 2010-01-18 (Original system by Vexorian, modified by MoCo):
//   - vjassification of system
//   - now works with latest patches

//==================================================================================================
// Independant Summons Configuration:
//
globals
    private Table SummonIdTab
    private unit array Summons[1]
    private unit array Masters[1]
    private integer N = 0
    private constant integer MAX_N = 64
endglobals

private constant function IndieSummon_maxdelay takes nothing returns real
    return 2.5 //* The max delay betwen orders issued to the summon
endfunction

private constant function IndieSummon_mindelay takes nothing returns real
    return 1.00 //* The min delay betwen orders issued to the summon
endfunction

private constant function IndieSummon_maxdistance takes nothing returns real
    return 1000.0 //* If the distance betwen the summon and the master is greater than this value,
                  //  The summon will move to the position of the master instead of attack move
endfunction

private constant function IndieSummon_cometomaxdist takes nothing returns real
    return 600.0 //* Max distance for issued orders to approach the master
endfunction

private constant function IndieSummon_cometomindist takes nothing returns real
    return 200.0 //* Min distance for issued orders to approach the master
endfunction

//==================================================================================================
private function SetSummonId takes unit summon returns integer
    set N = N + 1
    set SummonIdTab[GetUnitId(summon)] = N
    if N > MAX_N then
        set N = 0
    endif
    return SummonIdTab[GetUnitId(summon)]
endfunction

private function GetSummonId takes unit summon returns integer
    return SummonIdTab[GetUnitId(summon)]
endfunction

private function IndieSummon_GetMaster takes unit summon returns unit
    local integer id = GetSummonId(summon)
    return Masters[id]
    return null
endfunction

private function IndieSummon_StopAI takes unit summon returns nothing
    local integer id = GetSummonId(summon)
    set Masters[id] = null
endfunction

private function IndieSummon_Order takes unit summon, unit master returns nothing
    local integer o=GetUnitCurrentOrder(summon)
    local real tx=GetUnitX(master)
    local real ty=GetUnitY(master)
    local real angle
    local real dist

    set dist=Pow(tx-GetUnitX(summon),2) + Pow(ty-GetUnitY(summon),2)
    if (dist > (IndieSummon_maxdistance()*IndieSummon_maxdistance()) )  and (o == 0 or o == OrderId("attack") or o == OrderId("move") or o == OrderId("stop") or o==851971) then
        call IssuePointOrder(summon, "move", tx,ty)
    elseif dist >= (IndieSummon_cometomindist()*IndieSummon_cometomindist()) and (o == 0 or o == 851971) then
        set angle = GetRandomReal( GetUnitFacing(master)-80, GetUnitFacing(master)+80)
        if (ModuloInteger(GetUnitPointValue(summon),2)==0) then
            set angle=angle * bj_DEGTORAD
        else
            set angle=- angle * bj_DEGTORAD
        endif

        set dist = GetRandomReal(IndieSummon_cometomindist(), IndieSummon_cometomaxdist() )
        set tx=tx+dist*Cos(angle)
        set ty=ty+dist*Sin(angle)
        if not IssuePointOrder(summon, "attack", tx, ty ) then
            call IssuePointOrder(summon, "move", tx, ty )
        endif
    endif
    set summon=null
    set master=null
endfunction

private function IndieSummon_AntiSmart_Timer takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer id = GetTimerData(t)
    local unit s = Summons[id]       
    local unit m = Masters[id]
   
    if (GetUnitCurrentOrder(s)!=851971) then
        call DestroyTimer(t)
    else
        call IndieSummon_Order( s, m )
        call TimerStart(t,0.1,false,function IndieSummon_AntiSmart_Timer)
    endif
    set t = null
    set s = null
    set m = null
endfunction


private function IndieSummon_AntiSmart takes nothing returns nothing
    local timer t
    local integer id = GetSummonId(GetTriggerUnit())

    if (GetIssuedOrderId() == 851971) then
        set t=CreateTimer()
        call SetTimerData(t, id)
        call TimerStart(t,0,false,function IndieSummon_AntiSmart_Timer)
        set t=null
    endif
endfunction

private function IndieSummon_loop takes integer id returns nothing
    local unit summon = Summons[id] 
    local unit master // = Masters[id]
    local trigger smart=CreateTrigger()
    local integer n = 0
    local triggeraction ac = TriggerAddAction( smart, function IndieSummon_AntiSmart)
   
    call TriggerRegisterUnitEvent( smart, summon, EVENT_UNIT_ISSUED_TARGET_ORDER )
    call TriggerRegisterUnitEvent( smart, summon, EVENT_UNIT_ISSUED_POINT_ORDER )
    loop
        exitwhen (GetWidgetLife(summon)<=0)
        set master = Masters[id]
        if (master==null) then
            exitwhen true
        else
            call IndieSummon_Order( summon, master)
            call PolledWait( GetRandomReal( IndieSummon_mindelay(), IndieSummon_maxdelay() ))
        endif
    endloop
   
    set Masters[id] = null

    call TriggerRemoveAction(smart,ac)
    if smart != null then
        call DestroyTrigger(smart)
    endif

    set ac=null
    set summon=null
    set master=null
    set smart=null
endfunction

function IndieSummon_SetMaster takes unit summon, unit master returns nothing
    local integer id

    set id = SetSummonId(summon)

    set Masters[id] = master
    set Summons[id] = summon
   
    call IndieSummon_loop.execute(id)
endfunction

//===========================================================================
private function Init takes nothing returns nothing
    set SummonIdTab = Table.create()
endfunction

endlibrary

_________________
Revenir en haut
 Troll-Brain
Ri1kamoua


Inscrit le: 23 Aoû 2007
Messages: 7143
Sujets: 147
Spécialité en worldedit: le troll, le flood, la vulgarité, mon coeur balance
Médailles: 2 (En savoir plus...)
Rédacteur de tuto #3 (Quantité : 1) Grand mage créateur de sort (Quantité : 1)

MessagePosté le: 18/03/10 20:34    Sujet du message: Citer

J'ai pas tout lu mais il y a quelques petits trucs qui me "choquent" :

Jass:
private function SetSummonId takes unit summon returns integer
    set N = N + 1
    set SummonIdTab[GetUnitId(summon)] = N
    if N > MAX_N then
        set N = 0
    endif
    return SummonIdTab[GetUnitId(summon)]
endfunction

private function GetSummonId takes unit summon returns integer
    return SummonIdTab[GetUnitId(summon)]
endfunction

private function IndieSummon_GetMaster takes unit summon returns unit
    local integer id = GetSummonId(summon)
    return Masters[id]
    return null
endfunction


Jass:
private function SetSummonId takes unit summon returns integer
    set N = N + 1
    set SummonIdTab[GetUnitId(summon)] = N
    if N > MAX_N then
        set N = 0
    endif
    return N
endfunction

private function GetSummonId takes unit summon returns integer
    return SummonIdTab[GetUnitId(summon)]
endfunction

private function IndieSummon_GetMaster takes unit summon returns unit
    return Masters[GetSummonId(summon)]
endfunction



Sinon je supposes que ca s'utilise avec des unités ayant le statut "garde" pour que les commandes ne soient pas accessibles pour le joueur mais que l'unité lui appartienne, d'où l'anti-smart, car on peut toujours ordonner un clic droit.

J'ai horreur de ce rustinage car cela empêche l'unité de lancer des compétences non instantanées, mais je suppose que tu ne peux pas utiliser un joueur (neutre ou non) pour chaque joueur humain (ou geek) possible.

L'utilisation de PolledWait aussi, bref ca me semble pas très bien codé.
_________________
Le violet, c'est moche.
Revenir en haut
Voir le profil de l'utilisateur Envoyer un message privé
 jk2pach
Invité








MessagePosté le: 18/03/10 20:43    Sujet du message: Citer

J'utilise ce truc en attendant que Vexorian allège son système actuel, c'est plus "light".

Et ca fonctionne très bien pour ce que j'en fais.

Pour 300 Blast Them j'ai même fait une version un tout petit peu changée qui permet de l'utiliser ou de le désactiver (donc les unités ne sont pas en Ward, le but c'est juste que le joueur ne fasse pas de microgestion à côté du héro si il le veut).

Et les sorts fonctionnent pas mal.

EDIT

Je n'utilise plus ce truc, autant pour moi.

J'utilise celui posté en "library"
_________________
Revenir en haut
 Troll-Brain
Ri1kamoua


Inscrit le: 23 Aoû 2007
Messages: 7143
Sujets: 147
Spécialité en worldedit: le troll, le flood, la vulgarité, mon coeur balance
Médailles: 2 (En savoir plus...)
Rédacteur de tuto #3 (Quantité : 1) Grand mage créateur de sort (Quantité : 1)

MessagePosté le: 18/03/10 21:18    Sujet du message: Citer

Apocalypse a écrit:
J'utilise ce truc en attendant que Vexorian allège son système actuel, c'est plus "light".

Et ca fonctionne très bien pour ce que j'en fais.

Pour 300 Blast Them j'ai même fait une version un tout petit peu changée qui permet de l'utiliser ou de le désactiver (donc les unités ne sont pas en Ward, le but c'est juste que le joueur ne fasse pas de microgestion à côté du héro si il le veut).

Et les sorts fonctionnent pas mal.

EDIT

Je n'utilise plus ce truc, autant pour moi.

J'utilise celui posté en "library"


Je parles justement de la library IndieSummons.
Ce que je veux dire c'est que si le spell n'a pas un temps de cast instantané ou peut être interrompu car il fonctionne dans la durée, le joueur peut l'interrompre via un ordre clic droit.
Ce n'est qu'un exemple, ca peut être le cas aussi pour une attaque, etc.

Je suis certain que toutes les library que tu as mis même mis en "résolu" ne me conviendraient pas, maintenant si ca te va tant mieux, mais sache que tu n'as pas mon "approved" Razz
_________________
Le violet, c'est moche.
Revenir en haut
Voir le profil de l'utilisateur Envoyer un message privé
 jk2pach
Invité








MessagePosté le: 18/03/10 21:29    Sujet du message: Citer

Erf. Je vois.

Juste que je préfère prioriser sur ce qui n'a jamais été modifié vraiment et qui est structurellement le plus gourmand (trade et motherships, les timers. Les boucles, c'est juste pour apprendre à utiliser les hashtables dans ce cas précis où on peut les éviter).
_________________
Revenir en haut
Montrer les messages depuis:   
Poster un nouveau sujet   Répondre au sujet    Worldedit Index du Forum -> Aide sur les déclencheurs Toutes les heures sont au format GMT + 1 Heure
Page 1 sur 1
La question posée dans ce topic a été résolue !

 
Sauter vers:  
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


Powered by phpBB © 2001, 2005 phpBB Group
Traduction par : phpBB-fr.com