Posté le: 22/01/10 11:58 Sujet du message: Optimisation: Indepdant Summon
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
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)
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...)
Posté le: 18/03/10 20:34 Sujet du message:
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é. _________________
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" _________________
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...)
Posté le: 18/03/10 21:18 Sujet du message:
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" _________________
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). _________________
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