Foro especializado en Warcraft III y su editor
 
BuscarEntrar al ChatboxPortal del foroÍndiceSpellsRegistrarseConectarseGrupos de Usuarios
Eventos Actuales
¡ Bienvenido Invitado!

Editar Perfil

Tus temas
Tus Mensajes ()

Enlaces rápidos








Comparte | .
 

 Todo lo que necesites saber sobre Tablas Hash (o no?) •

Ver el tema anterior Ver el tema siguiente Ir abajo 
AutorMensaje
Marcos_M

avatar


Barra de Salud : Su salud está al 100% - Este usuario no ha recibido infracciones

Mensajes Mensajes : 3019
Reputación Reputación : 500
Monedas de oro : 9283
Monedas de Platino : 0

Inventario :



Mensaje(#) Tema: Todo lo que necesites saber sobre Tablas Hash (o no?) • Jue Jul 25, 2013 9:57 pm

Buenos días, tardes, noches n.n

Primero que nada, si no quieres leer nada te aconsejo que no mires el tutorial ya que no será de tu agrado y por favor eviten los comentarios de agradecimiento, porque no les sirven a nadie, si tienen algún agradecimiento pueden dar karma o mandarme un MP.
PD: Gerhalt como gran amigo que es se encargará de borrar esos comentarios.


Si permito los comentarios que contengan:
- Consejos(Que cambiar, que no quedó muy claro, que agregar)
- Pedidos de contenido(Que quisieras saber que no está en el tutorial)
- Dudas del tutorial(Si algo no te quedó claro, preguntá, seguramente no eres el único)

Índice:
1. ¿Qué es una Tabla Hash?
2. ¿Qué puedo hacer con una Tabla Hash?
3. Funciones básicas de una Tabla Hash
   a. Funciones de GUI para Tablas Hash
   b. Funciones de JASS para Tablas Hash
4. Formas simples de usar Tablas Hash
  a. En GUI
  b. En JASS
5. Formas complejas de usar Tablas Hash
 a. En GUI
 b. En JASS
6. Truquito para GUI .3
7. Mapa-Tutorial


¿Qué es una Tabla Hash?
Wikipedia: Una tabla hash es una estructura de datos que asocia llaves o claves con valores. La operación principal que soporta de manera eficiente es la búsqueda: permite el acceso a los elementos (todo lo que necesites guardar .3) almacenados a partir de una clave generada (usando el HandleId de un objeto o un rawcode, por ejemplo). Funciona transformando la clave con una función hash en un hash, un número que identifica la posición (casilla) donde la tabla hash localiza el valor deseado.

Forma en la que yo entiendo: Una tabla hash(por lo menos en WE) es una estructura que guarda valores(cualquier valor de war3) como un número entero o StringHash(una cadena de texto, se convierte en número) dentro de una clave(otro número, generalmente, el HandleId de un objeto o, a veces, en el rawcode de cualquier cosa) en tu tabla.


¿Qué puedo hacer con una Tabla Hash?
La verdadera pregunta debería ser: ¿Qué no puedes hacer con una Tabla Hash?
Los usos para la tabla hash dentro del WE son infinitos. Debido a que guardan los valores que deseemos, nos son útiles en todo momento, tanto si utilizas JASS o si utilizas GUI.
Por mi parte me gusta utilizar las tablas hash en casi todos mis sistemas cuando trabajo con items, ya que guardo en el rawcode de ellos todos los valores que necesito. En spells donde debo tomar valores independientes uno de otro(por ejemplo, manejar distintos rayos hacia distintos puntos), pero cada uno tiene sus propias ideas y les encontraré sus propias funcionalidades.


Funciones básicas de una Tabla Hash
a. Funciones de GUI para Tablas Hash
Las funciones de GUI para Tablas Hash son las siguientes:


Crea una Tabla Hash, esta recibe el nombre de "Last Created HashTable" e.e

Las funciones de guardado son prácticamente iguales


El valor a guardar puede ser casi cualquiera, pero los chicos de blizzard tienen funciones de GUI que tiran crítico en tu WE y te dan ganas de matar a alguien cuando te pasa. Esas funciones son las siguientes:
Tabla Hash - Save ItemPool Handle
Tabla Hash - Save Widget Handle
Tabla Hash - Save Ability Handle
Tabla Hash - Save Multiboarditem Handle
Tabla Hash - Save Trackable Handle
Tabla Hash - Save Region Handle
Tabla Hash - Save Eventid Handle
Tabla Hash - Save UnitPool Handle

Las funciones de cargado son iguales también y se cargan al momento de setear una variable:


Hay algunas variables imposibles de cargar con esta función, estas son las siguientes:
Conjuro Benéfico(Buff)
Caché del Juego
Clase de Objeto
Color de Jugador
Deformación de Terreno
Efecto Meteorológico
Forma de Terreno
Habilidad
Identificador(no sé que es esto)
Objeto Cámara
Orden
Raza
Sonido de Arma
Tabla Hash (Si cargas esto, el sueño podría colapsar)
Tipo de Ataque
Tipo de Daño
Tipo de Efecto (no entiendo para que sirve :I )
Tipo de Ruta
Tipo de Terreno
Tipo de Destructible
Tipo de Imagen
Tipo de Objeto
Tipo de Rayo
Tipo de Sonido
Tipo Técnico (actualización)
Tipo Ubersplat
Tipo de Unidad
Velocidad de Juego
A pesar de no poder cargarse mediante GUI, hay algunos que son variables creadas para GUI pero en realidad son otro tipo de variable, un buen ejemplo de esto es la variable de Habilidad, que en realidad es un número entero, más tarde hablaremos más de esto.


Esta función limpia totalmente la tabla hash.


Esta función limpia totalmente una clave de la tabla hash.


b. Funciones de JASS para Tablas Hash
Código:
InitHashtable    takes nothing returns hashtable
Importante función, crea una tabla hash (Se usa al momento de setear tu tabla hash)

Las funciones de guardado son las siguientes:
Código:
 SaveInteger takes hashtable table, integer parentKey, integer childKey, integer value returns nothing
  SaveReal takes hashtable table, integer parentKey, integer childKey, real value returns nothing
  SaveBoolean takes hashtable table, integer parentKey, integer childKey, boolean value returns nothing
  SaveStr takes hashtable table, integer parentKey, integer childKey, string value returns boolean
  SavePlayerHandle takes hashtable table, integer parentKey, integer childKey, player whichPlayer returns boolean
  SaveWidgetHandle takes hashtable table, integer parentKey, integer childKey, widget whichWidget returns boolean
  SaveDestructableHandle takes hashtable table, integer parentKey, integer childKey, destructable whichDestructable returns boolean
  SaveItemHandle takes hashtable table, integer parentKey, integer childKey, item whichItem returns boolean
  SaveUnitHandle takes hashtable table, integer parentKey, integer childKey, unit whichUnit returns boolean
  SaveAbilityHandle takes hashtable table, integer parentKey, integer childKey, ability whichAbility returns boolean
  SaveTimerHandle takes hashtable table, integer parentKey, integer childKey, timer whichTimer returns boolean
  SaveTriggerHandle takes hashtable table, integer parentKey, integer childKey, trigger whichTrigger returns boolean
  SaveTriggerConditionHandle takes hashtable table, integer parentKey, integer childKey, triggercondition whichTriggercondition returns boolean
  SaveTriggerActionHandle takes hashtable table, integer parentKey, integer childKey, triggeraction whichTriggeraction returns boolean
  SaveTriggerEventHandle takes hashtable table, integer parentKey, integer childKey, event whichEvent returns boolean
  SaveForceHandle takes hashtable table, integer parentKey, integer childKey, force whichForce returns boolean
  SaveGroupHandle takes hashtable table, integer parentKey, integer childKey, group whichGroup returns boolean
  SaveLocationHandle takes hashtable table, integer parentKey, integer childKey, location whichLocation returns boolean
  SaveRectHandle takes hashtable table, integer parentKey, integer childKey, rect whichRect returns boolean
  SaveBooleanExprHandle takes hashtable table, integer parentKey, integer childKey, boolexpr whichBoolexpr returns boolean
  SaveSoundHandle takes hashtable table, integer parentKey, integer childKey, sound whichSound returns boolean
  SaveEffectHandle takes hashtable table, integer parentKey, integer childKey, effect whichEffect returns boolean
  SaveUnitPoolHandle takes hashtable table, integer parentKey, integer childKey, unitpool whichUnitpool returns boolean
  SaveItemPoolHandle takes hashtable table, integer parentKey, integer childKey, itempool whichItempool returns boolean
  SaveQuestHandle takes hashtable table, integer parentKey, integer childKey, quest whichQuest returns boolean
  SaveQuestItemHandle takes hashtable table, integer parentKey, integer childKey, questitem whichQuestitem returns boolean
  SaveDefeatConditionHandle takes hashtable table, integer parentKey, integer childKey, defeatcondition whichDefeatcondition returns boolean
  SaveTimerDialogHandle takes hashtable table, integer parentKey, integer childKey, timerdialog whichTimerdialog returns boolean
  SaveLeaderboardHandle takes hashtable table, integer parentKey, integer childKey, leaderboard whichLeaderboard returns boolean
  SaveMultiboardHandle takes hashtable table, integer parentKey, integer childKey, multiboard whichMultiboard returns boolean
  SaveMultiboardItemHandle takes hashtable table, integer parentKey, integer childKey, multiboarditem whichMultiboarditem returns boolean
  SaveTrackableHandle takes hashtable table, integer parentKey, integer childKey, trackable whichTrackable returns boolean
  SaveDialogHandle takes hashtable table, integer parentKey, integer childKey, dialog whichDialog returns boolean
  SaveButtonHandle takes hashtable table, integer parentKey, integer childKey, button whichButton returns boolean
  SaveTextTagHandle takes hashtable table, integer parentKey, integer childKey, texttag whichTexttag returns boolean
  SaveLightningHandle takes hashtable table, integer parentKey, integer childKey, lightning whichLightning returns boolean
  SaveImageHandle takes hashtable table, integer parentKey, integer childKey, image whichImage returns boolean
  SaveUbersplatHandle takes hashtable table, integer parentKey, integer childKey, ubersplat whichUbersplat returns boolean
  SaveRegionHandle takes hashtable table, integer parentKey, integer childKey, region whichRegion returns boolean
  SaveFogStateHandle takes hashtable table, integer parentKey, integer childKey, fogstate whichFogState returns boolean
  SaveFogModifierHandle takes hashtable table, integer parentKey, integer childKey, fogmodifier whichFogModifier returns boolean
  SaveAgentHandle takes hashtable table, integer parentKey, integer childKey, agent whichAgent returns boolean
  SaveHashtableHandle takes hashtable table, integer parentKey, integer childKey, hashtable whichHashtable returns boolean
Bueno, no daré explicación de uno por uno por su gran cantidad y son fáciles de entender que guarda cada uno. Pero lo básico es esto
 Cada función toma la tabla hash donde guardarás, la clave en donde guardarás, el valor que tomará lo que guardas, y el objeto que guardas. Esto es un ejemplo básico para guardar una unidad.
Código:
call SaveUnitHandle(udg_HashTable, GetHandleId(GetTriggerUnit()), 1, GetSpellTargetUnit())
En el ejemplo, guardamos en "HashTable", en la clave HandleId de Triggering Unit, con el valor "1", a La unidad objetivo del spell.

Las funciones de cargado son las siguientes:
Código:
 LoadInteger takes hashtable table, integer parentKey, integer childKey returns integer
  LoadReal takes hashtable table, integer parentKey, integer childKey returns real
  LoadBoolean    takes hashtable table, integer parentKey, integer childKey returns boolean
  LoadStr takes hashtable table, integer parentKey, integer childKey returns string
  LoadPlayerHandle takes hashtable table, integer parentKey, integer childKey returns player
  LoadWidgetHandle takes hashtable table, integer parentKey, integer childKey returns widget
  LoadDestructableHandle takes hashtable table, integer parentKey, integer childKey returns destructable
  LoadItemHandle takes hashtable table, integer parentKey, integer childKey returns item
  LoadUnitHandle takes hashtable table, integer parentKey, integer childKey returns unit
  LoadAbilityHandle takes hashtable table, integer parentKey, integer childKey returns ability
  LoadTimerHandle takes hashtable table, integer parentKey, integer childKey returns timer
  LoadTriggerHandle takes hashtable table, integer parentKey, integer childKey returns trigger
  LoadTriggerConditionHandle takes hashtable table, integer parentKey, integer childKey returns triggercondition
  LoadTriggerActionHandle takes hashtable table, integer parentKey, integer childKey returns triggeraction
  LoadTriggerEventHandle takes hashtable table, integer parentKey, integer childKey returns event
  LoadForceHandle takes hashtable table, integer parentKey, integer childKey returns force
  LoadGroupHandle takes hashtable table, integer parentKey, integer childKey returns group
  LoadLocationHandle takes hashtable table, integer parentKey, integer childKey returns location
  LoadRectHandle takes hashtable table, integer parentKey, integer childKey returns rect
  LoadBooleanExprHandle takes hashtable table, integer parentKey, integer childKey returns boolexpr
  LoadSoundHandle takes hashtable table, integer parentKey, integer childKey returns sound
  LoadEffectHandle takes hashtable table, integer parentKey, integer childKey returns effect
  LoadUnitPoolHandle takes hashtable table, integer parentKey, integer childKey returns unitpool
  LoadItemPoolHandle takes hashtable table, integer parentKey, integer childKey returns itempool
  LoadQuestHandle takes hashtable table, integer parentKey, integer childKey returns quest
  LoadQuestItemHandle takes hashtable table, integer parentKey, integer childKey returns questitem
  LoadDefeatConditionHandle takes hashtable table, integer parentKey, integer childKey returns defeatcondition
  LoadTimerDialogHandle takes hashtable table, integer parentKey, integer childKey returns timerdialog
  LoadLeaderboardHandle takes hashtable table, integer parentKey, integer childKey returns leaderboard
  LoadMultiboardHandle takes hashtable table, integer parentKey, integer childKey returns multiboard
  LoadMultiboardItemHandle takes hashtable table, integer parentKey, integer childKey returns multiboarditem
  LoadTrackableHandle takes hashtable table, integer parentKey, integer childKey returns trackable
  LoadDialogHandle takes hashtable table, integer parentKey, integer childKey returns dialog
  LoadButtonHandle takes hashtable table, integer parentKey, integer childKey returns button
  LoadTextTagHandle takes hashtable table, integer parentKey, integer childKey returns texttag
  LoadLightningHandle takes hashtable table, integer parentKey, integer childKey returns lightning
  LoadImageHandle takes hashtable table, integer parentKey, integer childKey returns image
  LoadUbersplatHandle takes hashtable table, integer parentKey, integer childKey returns ubersplat
  LoadRegionHandle takes hashtable table, integer parentKey, integer childKey returns region
  LoadFogStateHandle takes hashtable table, integer parentKey, integer childKey returns fogstate
  LoadFogModifierHandle takes hashtable table, integer parentKey, integer childKey returns fogmodifier
  LoadHashtableHandle takes hashtable table, integer parentKey, integer childKey returns hashtable
Un ejemplo sería
Código:
Set unit = LoadUnitHandle(udg_HashTable, GetHandleId(GetTriggerUnit()), 1)
Esto carga el valor "1", en la clave HandleId de Triggering Unit, en la tabla hash "HashTable"

Estas son las funciones de "Limpiado" de Tabla Hash:
Código:
 RemoveSavedInteger takes hashtable table, integer parentKey, integer childKey returns nothing
  RemoveSavedReal takes hashtable table, integer parentKey, integer childKey returns nothing
  RemoveSavedBoolean takes hashtable table, integer parentKey, integer childKey returns nothing
  RemoveSavedString takes hashtable table, integer parentKey, integer childKey returns nothing
  RemoveSavedHandle takes hashtable table, integer parentKey, integer childKey returns nothing
Estas funciones sirven para remover el valor especificado(Handle puede ser todo que no sea los 4 de arriba xD), aunque no se aconseja ya que no se suele remover un solo valor.

Código:
 FlushParentHashtable takes hashtable table returns nothing
Esto limpia la Tabla Hash

Código:
 FlushChildHashtable takes hashtable table, integer parentKey returns nothing
Esto limpia una clave de una Tabla Hash


Formas simples de usar Tablas Hash:
a. En GUI:

Algo simple de hacer es un spell instantáneo(que daña inmediatamente), las tablas hash no suelen ser necesarias para algo como esto, pero nosotros haremos un spell copado :gafas:

Descripción:
Spoiler:
 


Explicaré acción por acción. Si no sabes setear el evento y la condición te aconsejo que practiques solo en WE o pidas ayuda en la chat, eso es super básico de GUI

[gui]Set Real = (150.00 x (Real((Level of Carga Estática  for (Triggering unit)))))[/gui]
Esto sirve para setear el daño usando la función Arithmetic y Conversión - Convert Integer to Real

[gui]Set Unidad = (Load 1 of (Key (Triggering unit)) in TablaHash)[/gui]
Esto carga la unidad del casteo anterior. La función se llama Tabla Hash - Get Handle Id. Si no entiedes que hace el "1" y la "Key", no leíste con atención

[gui] If (All Conditions are True) then do (Then Actions) else do (Else Actions)
   Si: Condiciones
        Unidad No igual a Ninguna unidad
   Entonces: Acciones
       Efecto especial - Create a special effect attached to the origin of Unidad using Abilities\Spells\Orc\Purge\PurgeBuffTarget.mdl
       Efecto especial - Destroy (Last created special effect)
       Unidad - Cause (Triggering unit) to damage Unidad, dealing Real damage of attack type Conjuros and damage type Relámpago
   Otros: Acciones[/gui]
Un If que sirve para detectar si Unidad es una unidad y no es una variable vacía, para causarle el daño y creamos un efecto para que quede tan feo (La imagen la hice antes de colocarle el efecto xD)

[gui] Unidad - Cause (Triggering unit) to damage (Target unit of ability being cast), dealing Real damage of attack type Conjuros and damage type Relámpago[/gui]
Dañamos al objetivo

[gui] Tabla hash - Save Handle Of(Target unit of ability being cast) as 1 of (Key (Triggering unit)) in TablaHash[/gui]
Guardamos el objetivo para que sea usado en el próximo casteo


También podemos usarlo para un pequeño sistema. En este caso un sistema para recuperar el último casteo de una unidad, preparanse, porque se usa unos super custom scripts. Y sus respectivos usos

Descripción
Spoiler:
 


Este es el sistema super simple, fácil de entender para el conocedor y el no conocedor

[gui] Multiple FunctionsIf (All Conditions are True) then do (Then Actions) else do (Else Actions)
   Si: Condiciones
         Multiple ConditionsOr - Any (Conditions) are true
           Condiciones
              (Ability being cast) Igual a  Restaurar Spell
               (Ability being cast) Igual a  Robar Spell
   Entonces: Acciones
       Skip remaining actions
   Otros: Acciones
[/gui]
If then else donde filtro las habilidad que no deseo que el sistema tome(No coloco esto directamente en las condiciones porque por alguna razón, me reconocía estas 2 habilidades igual )

[gui] Custom script:   call SaveInteger( udg_TablaHash, GetHandleId(GetTriggerUnit()), 0,GetSpellAbilityId()  )[/gui]
Esta acción guarda un número entero, en este caso, el RawCode de la habilidad casteada. Debido a que GUI no deja guardar ni cargar variables de tipo habilidad, nosotros usamos números enteros.
¿Por qué?
Porque las variables de tipo "habilidad" son en realidad variables de tipo "Número entero" creadas especialmente para GUI y hacernos las cosas "más fáciles", pero son descuidados y nos dejan con baches como el problema de no poder cargarlas ni guardarlas en una tabla hash. Y hay otras variables que también son números enteros ocultados, luego las descubriremos.

Bueno, para explicar la acción
[ljass]call Save Integer[/ljass]
Llamamos la función cuyo nombre es "SaveInteger" (Guardar número entero)
[ljass]( udg_TablaHash,[/ljass]
Abrimos paréntesis que indica que la función que acabamos de llamar tomará los valores dentro. Primero necesita una tabla hash, esta será "TablaHash". La coma separa los valores.
[ljass]GetHandleId(GetTriggerUnit()),[/ljass]
Esta función "GetHandleId" sirve para tomar el Id del Handle (se, no sé bien que significa) de Triggering Unit, o sea, la unidad caster. (Vean como se designa Triggering Unit y vean los paréntesis)
[ljass]0,[/ljass]
El "0" es el valor entero que tomará el valor a guardar dentro de nuestra tabla hash. (Notese que en el ejemplo anterior usamos 1 y ahora 0, esto es para evitar que los valores se sobreescriban y los perdamos)
[ljass]GetSpellAbilityId()  )[/ljass]
La función "GetSpellAbilityId" nos devolverá el Rawcode de nuestra habilidad casteada. Cerramos el paréntesis para evitar errores y el custom script se termina.


-Pero... ¿De qué me sirve el sistema si solo guarda eso?


Ahora pondré los ejemplos ¬¬

Descripción
Spoiler:
 


Es un spell simple, pero a mi me encanta xD

[gui] Set NumEntero = (Load -1 of (Key (Triggering unit)) from TablaHash)[/gui]
Cargamos el spell robado actual, en caso de no existir devuelve el valor "null"

[gui] Custom script:   call UnitRemoveAbility(GetTriggerUnit(), udg_NumEntero)[/gui]
En GUI: Unidad - Remove Ability from (Triggering unit)
Remueve la habilidad cargada, se usa un custom script porque la acción de GUI no permite números enteros

[gui] Set NumEntero = (Load 0 of (Key (Target unit of ability being cast)) from TablaHash)[/gui]
Ahora sí, cargamos el spell a robar.

[gui] Custom script:   call UnitAddAbility(GetTriggerUnit(), udg_NumEntero)[/gui]
En GUI: 33  Unidad - Add Ability to (Triggering unit)
Agrega la habilidad robada, se usa un custom script porque la acción de GUI no permite números enteros

[gui] Custom script:   call SetUnitAbilityLevel(GetTriggerUnit(), udg_NumEntero, GetUnitAbilityLevel(GetSpellTargetUnit(), udg_NumEntero) )[/gui]
En GUI:33  Unidad - Set level of Ability for (Triggering unit) to (Level of Ability for (Target unit of ability being cast))
Seteamos el nivel de la habilidad al nivel correcto, se usa un custom script porque la acción de GUI no permite números enteros

[gui] Tabla hash - Save NumEntero as -1 of (Key (Triggering unit)) in TablaHash[/gui]
Por último, guardamos la habilidad robada para ser removida al robar una nueva


Ahora, otro ejemplo, esta vez, un skill menos ilegal

Descripción:
Spoiler:
 


Super simple, por eso esta es la sección de formas simples de usar una tabla hash

[gui] Set NumEntero = (Load 0 of (Key (Triggering unit)) from TablaHash)[/gui]
Cargamos el último spell lanzado

[gui] Custom script:   set udg_NumEntero_2 = GetUnitAbilityLevel(GetTriggerUnit(), udg_NumEntero)[/gui]
Seteamos una variable de número entero. "GetUnitAbilityLevel" es una función que toma una unidad y una habilidad(número entero) y te devuelve el nivel de esa habilidad para la unidad designada

[gui] Custom script:   call UnitRemoveAbility(GetTriggerUnit(), udg_NumEntero)[/gui]
Removemos la habilidad de la unidad

[gui] Custom script:   call UnitAddAbility(GetTriggerUnit(), udg_NumEntero)[/gui]
Se la agregamos

[gui] Custom script:   call SetUnitAbilityLevel(GetTriggerUnit(), udg_NumEntero, udg_NumEntero_2)[/gui]
Y le seteamos el nivel correctamente


b. En JASS:
Algo para que uso mucho las tablas hash es para asociar valores, así accedo a ambos desde uno y otro. Antes de empezar con el JASS, te aconsejo descargarte el NewGen:
http://www.worldedit.com.ar/forum/viewtopic.php?f=85&t=6783
(No encontré el link en este foro)

En este ejemplo asociaré 2 torres ya colocadas en el mapa, si se destruye una, la otra será destruida también, para saber como designarlas, las seteo en una variable en un deto de GUI de esta forma


(Los comentarios son para saber cuál es cual)

Al pasarlo a deto de JASS (Editar. Convertir a texto personalizado)

[jass]function Trig_Asociando_Valores_Actions takes nothing returns nothing
   // Roja 1
   set udg_Unidad = gg_unit_hctw_0011
   // Roja 2
   set udg_Unidad = gg_unit_hctw_0012
   // Azul 1
   set udg_Unidad = gg_unit_hctw_0009
   // Azul 2
   set udg_Unidad = gg_unit_hctw_0010
endfunction[/jass]

Quedará algo así luego de modificarlo y asociarlo

[jass]function Trig_Asociando_Valores_Actions takes nothing returns nothing
   local unit TorreRoja1 = gg_unit_hctw_0011
   local unit TorreRoja2 = gg_unit_hctw_0012
   local unit TorreAzul1 = gg_unit_hctw_0009
   local unit TorreAzul2 = gg_unit_hctw_0010
   call SaveUnitHandle(udg_TablaHash, GetHandleId(TorreRoja1), 2, TorreRoja2)
   call SaveUnitHandle(udg_TablaHash, GetHandleId(TorreRoja2), 2, TorreRoja1)
   call SaveUnitHandle(udg_TablaHash, GetHandleId(TorreAzul1), 2, TorreAzul2)
   call SaveUnitHandle(udg_TablaHash, GetHandleId(TorreAzul2), 2, TorreAzul1)
endfunction

//===========================================================================
function InitTrig_Asociando_Valores takes nothing returns nothing
   local trigger t = CreateTrigger(  )
   call TriggerRegisterTimerEvent( t, 0.50, false )
   call TriggerAddAction( t, function Trig_Asociando_Valores_Actions )
   set t = null
endfunction[/jass]

El evento es muy importante sin eso el deto no hace nada
Ahora, como ya sabrán si están aquí en JASS, un deto puede tener muchos detos (se, está re loco), así que crearemos nuestros detos para nuestras torres asociadas

[jass]function AccionesAsociadas takes nothing returns nothing
   local unit Torre = GetTriggerUnit()
   local unit Torre2 = LoadUnitHandle(udg_TablaHash, GetHandleId(Torre), 2)
   call KillUnit(Torre2)
endfunction

function Trig_Asociando_Valores_Actions takes nothing returns nothing
   local unit TorreRoja1 = gg_unit_hctw_0011
   local unit TorreRoja2 = gg_unit_hctw_0012
   local unit TorreAzul1 = gg_unit_hctw_0009
   local unit TorreAzul2 = gg_unit_hctw_0010
   local trigger Rojo = CreateTrigger()
   local trigger Azul = CreateTrigger()
   call SaveUnitHandle(udg_TablaHash, GetHandleId(TorreRoja1), 2, TorreRoja2)
   call SaveUnitHandle(udg_TablaHash, GetHandleId(TorreRoja2), 2, TorreRoja1)
   call SaveUnitHandle(udg_TablaHash, GetHandleId(TorreAzul1), 2, TorreAzul2)
   call SaveUnitHandle(udg_TablaHash, GetHandleId(TorreAzul2), 2, TorreAzul1)
   call TriggerRegisterUnitEvent(Rojo, TorreRoja1, EVENT_UNIT_DEATH)
   call TriggerRegisterUnitEvent(Rojo, TorreRoja1, EVENT_UNIT_DEATH)
   call TriggerRegisterUnitEvent(Azul, TorreAzul1, EVENT_UNIT_DEATH)
   call TriggerRegisterUnitEvent(Azul, TorreAzul2, EVENT_UNIT_DEATH)
   call TriggerAddAction(Rojo, function AccionesAsociadas)
   call TriggerAddAction(Azul, function AccionesAsociadas)
endfunction

//===========================================================================
function InitTrig_Asociando_Valores takes nothing returns nothing
   local trigger t = CreateTrigger(  )
   call TriggerRegisterTimerEvent( t, 0.50, false )
   call TriggerAddAction( t, function Trig_Asociando_Valores_Actions )
   set t = null
endfunction[/jass]

Y nuestro trigger está hecho. Sin embargo, tiene leaks todavía. Exacto, no se nullean las variables locales, pero también, tiene el error de que los detos quedan ahí cuando solo los usamos una vez. Así que vamos a eliminarlos luego de usarlos también

[jass]function AccionesAsociadas takes nothing returns nothing
   local unit Torre = GetTriggerUnit()
   local unit Torre2 = LoadUnitHandle(udg_TablaHash, GetHandleId(Torre), 2)
   call DestroyTrigger(GetTriggeringTrigger())
   call KillUnit(Torre2)
   call FlushChildHashtable(udg_TablaHash, GetHandleId(Torre))
   call FlushChildHashtable(udg_TablaHash, GetHandleId(Torre2))
   set Torre = null
   set Torre2 = null
endfunction

function Trig_Asociando_Valores_Actions takes nothing returns nothing
   local unit TorreRoja1 = gg_unit_hctw_0011
   local unit TorreRoja2 = gg_unit_hctw_0012
   local unit TorreAzul1 = gg_unit_hctw_0009
   local unit TorreAzul2 = gg_unit_hctw_0010
   local trigger Rojo = CreateTrigger()
   local trigger Azul = CreateTrigger()
   call SaveUnitHandle(udg_TablaHash, GetHandleId(TorreRoja1), 2, TorreRoja2)
   call SaveUnitHandle(udg_TablaHash, GetHandleId(TorreRoja2), 2, TorreRoja1)
   call SaveUnitHandle(udg_TablaHash, GetHandleId(TorreAzul1), 2, TorreAzul2)
   call SaveUnitHandle(udg_TablaHash, GetHandleId(TorreAzul2), 2, TorreAzul1)
   call TriggerRegisterUnitEvent(Rojo, TorreRoja1, EVENT_UNIT_DEATH)
   call TriggerRegisterUnitEvent(Rojo, TorreRoja1, EVENT_UNIT_DEATH)
   call TriggerRegisterUnitEvent(Azul, TorreAzul1, EVENT_UNIT_DEATH)
   call TriggerRegisterUnitEvent(Azul, TorreAzul2, EVENT_UNIT_DEATH)
   call TriggerAddAction(Rojo, function AccionesAsociadas)
   call TriggerAddAction(Azul, function AccionesAsociadas)
   call DestroyTrigger(GetTriggeringTrigger())
   set TorreRoja1 = null
   set TorreRoja2 = null
   set TorreAzul1 = null
   set TorreAzul2 = null
   set Rojo = null
   set Azul = null
endfunction

//===========================================================================
function InitTrig_Asociando_Valores takes nothing returns nothing
   local trigger t = CreateTrigger(  )
   call TriggerRegisterTimerEvent( t, 0.50, false )
   call TriggerAddAction( t, function Trig_Asociando_Valores_Actions )
   set t = null
endfunction[/jass]

Y ahora sí, nuestros detos están terminados y nuestras torres asociadas


Ahora un spell en JASS, como es un ejemplo simple no usaré librerías (Yo suelo utilizar Faux por su simpleza)

Descripción
Spoiler:
 

[jass]function TimerFreeze takes nothing returns nothing
   local timer T = GetExpiredTimer() //Recuperamos el timer
   local unit Target = LoadUnitHandle(udg_TablaHash, GetHandleId(T), 1) //Cargamos al Target
   local effect Efecto = LoadEffectHandle(udg_TablaHash, GetHandleId(T), 2) //Cargamos el efecto
   call PauseUnit(Target, false) //Lo despausamos
   call SetUnitTimeScale( Target, 1 ) //El target recupera la movilidad
   call DestroyEffect(Efecto) //Destruimos el efecto
   call PauseTimer(T) //Pausamos al timer para después destruirlo(me dijeron que se debe hacer asì)
   call FlushChildHashtable(udg_TablaHash, GetHandleId(T)) //Limpiamos el timer para evitar leaks
   call DestroyTimer(T) //Destruimos el timer
   set T = null
   set Target = null
   set Efecto = null
endfunction

function Freeze_Conditions takes nothing returns boolean
   return GetSpellAbilityId() == 'A003'
endfunction

function Freeze_Actions takes nothing returns nothing
   local unit Caster = GetTriggerUnit() //Triggering Unit
   local unit Target = GetSpellTargetUnit() //Objetivo del spell
   local real Duracion = GetUnitAbilityLevel(Caster, GetSpellAbilityId()) * 0.8 // Duracion del spell
   local timer T = CreateTimer() //Creamos un timer que usaremos luego
   local effect Efecto = AddSpecialEffectTarget("Abilities\\Weapons\\FrostWyrmMissile\\FrostWyrmMissile.mdl", Target, "chest")
   //Creamos un efecto sobre el objetivo para que se vea lindo
   call SaveUnitHandle(udg_TablaHash, GetHandleId(T), 1, Target) //Guardamos al target
   call SaveEffectHandle(udg_TablaHash, GetHandleId(T), 2, Efecto) //Guardamos el efecto
   call TimerStart(T, Duracion, false, function TimerFreeze) //Iniciamos el timer
   call SetUnitTimeScale( Target, 0 ) //Esto es para darle efecto de congelación
   call PauseUnit(Target, true) //Pausamos la unidad
   set Caster = null
   set Target = null
   set T = null
   set Efecto = null
endfunction

//===========================================================================
function InitTrig_Freeze takes nothing returns nothing
   local trigger t = CreateTrigger(  )
   call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
   call TriggerAddCondition( t, Condition( function Freeze_Conditions ) )
   call TriggerAddAction( t, function Freeze_Actions )
   set t = null
endfunction[/jass]
El deto es simple, aunque no lo creas. Pasaré a explicar las acciones no tan básicas

[jass]local effect Efecto = AddSpecialEffectTarget("Abilities\\Weapons\\FrostWyrmMissile\\FrostWyrmMissile.mdl", Target, "chest")[/jass]
Declaramos un efecto y lo agregamos al target con la función "AddSpecialEffectTarget", que toma una string(nuestro nombre del modelo para el efecto), un widget(en este caso nuestra unidad), y otra string(a donde "attacharemos" nuestro efecto)
Si no sabes como determinar la string del nombre de modelo, simplemente crea un deto, coloca la acción de efecto especial con tu modelo, pasalo a deto JASS y copias la string.

[jass]call TimerStart(T, Duracion, false, function TimerFreeze)[/jass]
Esta función sirve para iniciar un timer. Toma un timer, un valor real que será la duración, una booleana si se repite o no, y una function "callback", esto significa que al terminar llamará esa función. Recuerden que la función SIEMPRE debe ser declarada antes para que el deto la pueda "encontrar".

[jass]call SetUnitTimeScale( Target, 0 )
call PauseUnit(Target, true)[/jass]
En GUI:
[gui] Animación - Change Target's animation speed to 0.00% of its original speed
 Unidad - Activar pausa Target[/gui]

Recuerden siempre pausar el timer antes de destruirlo porque creo, ocasiona leaks(uno aprende a hacerlo de un modo pero no pregunta porque hacerlo así)

PD: Confío en que entendieron como setear variables y cargarlas.

Si no les queda claro con ese tag feo(extraño los tags del otro foro u.u ). Siempre pueden descargar el mapa tutorial al final del post



Última edición por Marcos_M el Mar Sep 26, 2017 9:11 pm, editado 4 veces
Volver arriba Ir abajo
Marcos_M

avatar


Barra de Salud : Su salud está al 100% - Este usuario no ha recibido infracciones

Mensajes Mensajes : 3019
Reputación Reputación : 500
Monedas de oro : 9283
Monedas de Platino : 0

Inventario :



Mensaje(#) Tema: Re: Todo lo que necesites saber sobre Tablas Hash (o no?) • Jue Jul 25, 2013 9:58 pm

Formas complejas de usar Tablas Hash:
a. En GUI:

Ahora empezamos con la práctica pesada :gafas:

Empezaremos con un sistema simple pero elegante hecho por mí con la ayuda de Angelcraft (Gracias Angie .3)

Descripción:
Spoiler:
 

Init


Loop


Explicando de forma rápida..

[gui]Grupo de unidad - Pick every unit in TiempoGrupo and do (Actions)
   Bucle: Acciones[/gui]
Tomamos las unidades en el grupo

[gui]       Set ManaTiempo = (Maná of (Picked unit))
       Set VidaTiempo = (Vida of (Picked unit))
       Set AnguloTiempo = (Facing of (Picked unit))
       Custom script:   set udg_XTiempo = GetUnitX(GetEnumUnit())
       Custom script:   set udg_YTiempo = GetUnitY(GetEnumUnit())[/gui]
Seteamos la posición, el maná, la vida y el ángulo de la unidad

[gui]       Tabla hash - Save ManaTiempo as (1 + (TiempoContador x 10)) of (Key (Picked unit)) in HashtableTiempo
       Tabla hash - Save VidaTiempo as (2 + (TiempoContador x 10)) of (Key (Picked unit)) in HashtableTiempo
       Tabla hash - Save XTiempo as (3 + (10 x TiempoContador)) of (Key (Picked unit)) in HashtableTiempo
       Tabla hash - Save AnguloTiempo as (4 + (TiempoContador x 10)) of (Key (Picked unit)) in HashtableTiempo
       Tabla hash - Save YTiempo as (5 + (10 x TiempoContador)) of (Key (Picked unit)) in HashtableTiempo
[/gui]
Guardamos dichos valores en la tabla (Notese la operación aritmética usada, esto sirve para que los valores no se sobreescriban. Así, en el segundo 0 se guardan valores como 1,2,3,4 y 5. En el segundo 1, tomarán el valor de 10,20,30,40 y 50, etc. )

[gui]Set TiempoContador = (TiempoContador + 1)
Multiple FunctionsIf (All Conditions are True) then do (Then Actions) else do (Else Actions)
   Si: Condiciones
       TiempoContador Mayor que (>) 1000
   Entonces: Acciones
       Set TiempoContador = 0
   Otros: Acciones[/gui]
Y fuera del loop. Aumentamos el contador de tiempo y el if es para resetearlo a 0, pueden elegir cualquier valor por debajo de 8192 creo. A mi me dijeron que ponga 1000 xD

Te dije que el sistema es simple, pero es elegante


:footmen: :muerto: :footmen: 
Alguien más que se queje?? ¬¬
...

Bien, entonces. Prosigamos

Un par de spells que usen el sistema aquí presentado

Descripción
Spoiler:
 



[gui]Set TiempoContador = (TiempoContador - (2 x (2 x (Level of (Ability being cast) for (Triggering unit)))))
Multiple FunctionsIf (All Conditions are True) then do (Then Actions) else do (Else Actions)
   Si: Condiciones
       TiempoContador Menor que (<) 0
   Entonces: Acciones
       Set TiempoContador = (1000 + TiempoContador)
   Otros: Acciones[/gui]
Si usan el sistema, primero deben designar los segundos que quieren volver en el tiempo. El If, es para evitar bugs

[gui]Multiple FunctionsIf (All Conditions are True) then do (Then Actions) else do (Else Actions)
   Si: Condiciones
       ((Target unit of ability being cast) is an illusion) Igual a True
   Entonces: Acciones
       Unidad - Kill (Target unit of ability being cast)
       Set TiempoContador = (TiempoContador + (2 x (2 x (Level of (Ability being cast) for (Triggering unit)))))
        Multiple FunctionsIf (All Conditions are True) then do (Then Actions) else do (Else Actions)
           Si: Condiciones
               TiempoContador Mayor que (>) 1000
           Entonces: Acciones
               Set TiempoContador = (TiempoContador - 1000)
           Otros: Acciones
       Skip remaining actions
   Otros: Acciones[/gui]
Este If, sirve para evitar lanzarle el skill a las ilusiones, ya que no son registradas en el sistema.

[gui]If (All Conditions are True) then do (Then Actions) else do (Else Actions)
   Si: Condiciones
       ((Target unit of ability being cast) belongs to an enemy of (Owner of (Triggering unit))) Igual a True[/gui]
Este if es para diferenciar entre unidad aliada y unidad enemiga.

[gui]   Entonces: Acciones
       Set ManaTiempo = (Load (1 + (TiempoContador x 10)) of (Key (Target unit of ability being cast)) from HashtableTiempo)
       Set XTiempo = (Load (3 + (10 x TiempoContador)) of (Key (Target unit of ability being cast)) from HashtableTiempo)
       Set YTiempo = (Load (5 + (10 x TiempoContador)) of (Key (Target unit of ability being cast)) from HashtableTiempo)
       Set PuntoTiempo = (Point(XTiempo, YTiempo))
       Set AnguloTiempo = (Load (4 + (TiempoContador x 10)) of (Key (Target unit of ability being cast)) from HashtableTiempo)[/gui]
Cargamos los valores que usaremos, si es enemiga, no usaremos la vida porque vamos a dañarlo

[gui]       Unidad - Move (Target unit of ability being cast) instantly to PuntoTiempo, facing AnguloTiempo degrees
       Unidad - Set mana of (Target unit of ability being cast) to ManaTiempo
       Unidad - Cause (Triggering unit) to damage (Target unit of ability being cast), dealing (-10.00 + (70.00 x (Real((Level of (Ability being cast) for (Triggering unit)))))) damage of attack type Caos and damage type Universal[/gui]
Ahora las acciones, lo movemos al punto orientado hacia el ángulo y le seteamos su maná(¿por qué hago que el enemigo recupere maná? no sé )
Y lo dañamos con daño puro (esa combinación de daño es irreducible, pero si usas triggers si se puede Razz)

[gui]   Otros: Acciones
       Set ManaTiempo = (Load (1 + (TiempoContador x 10)) of (Key (Target unit of ability being cast)) from HashtableTiempo)
       Set XTiempo = (Load (3 + (10 x TiempoContador)) of (Key (Target unit of ability being cast)) from HashtableTiempo)
       Set YTiempo = (Load (5 + (10 x TiempoContador)) of (Key (Target unit of ability being cast)) from HashtableTiempo)
       Set AnguloTiempo = (Load (4 + (TiempoContador x 10)) of (Key (Target unit of ability being cast)) from HashtableTiempo)
       Set VidaTiempo = (Load (2 + (TiempoContador x 10)) of (Key (Target unit of ability being cast)) from HashtableTiempo)[/gui]
Si es aliada cargamos los 4 valores.

[gui]       Custom script:   call SetUnitX(GetSpellTargetUnit(), udg_XTiempo)
       Custom script:   call SetUnitY(GetSpellTargetUnit(), udg_YTiempo)
       Unidad - Make (Target unit of ability being cast) face AnguloTiempo over 0.00 seconds
       Unidad - Set mana of (Target unit of ability being cast) to ManaTiempo
       Unidad - Set life of (Target unit of ability being cast) to VidaTiempo[/gui]
Seteamos su posición con SetUnitX y SetUnitY. ¿Por qué? Porque con esto evitamos interrumpir a nuestra unidad aliada. (Es re imba esto, tu aliada hace TP, se acerca a los enemigos y empieza a castear una habi channeling, vos lo devuelves a base y sigue con la habi channeling xD)
Hacemos que vea dicha ángulo y seteamos su maná y vida correctamente


[gui]Set TiempoContador = (TiempoContador + (2 x (2 x (Level of (Ability being cast) for (Triggering unit)))))
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
   Si: Condiciones
       TiempoContador Mayor que 1000
   Entonces: Acciones
       Set TiempoContador = (TiempoContador - 1000)
   Otros: Acciones[/gui]
Y devolvemos el tiempo a su valor correcto para evitar cualquier bug

Es un spell re imba, re copado y re drogón. Puedes denegar a tus aliados con esto xD
Y sí, es un spell viejo por eso tiene gran cantidad de bugs como si cargas la vida y es igual a 0 tu aliado se muere..


Descripción
Spoiler:
 



Este spell recibirá menos explicación ya que funciona casi igual al otro spell

[gui]Grupo de unidad - Pick every unit in TiempoGrupo and do (Actions)
   Bucle: Acciones[/gui]
Tomamos cada héroe registrado

[gui]       If (All Conditions are True) then do (Then Actions) else do (Else Actions)
           Si: Condiciones
               (Picked unit) No igual a (Triggering unit)[/gui]
La unidad caster recibirá un trato diferente a las demás unidades

[gui]           Entonces: Acciones
               If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                   Si: Condiciones
                      ((Picked unit) belongs to an enemy of (Owner of (Triggering unit))) Igual a True
                   Entonces: Acciones
                       Set ManaTiempo = (Load (1 + (TiempoContador x 10)) of (Key (Picked unit)) from HashtableTiempo)
                       Set XTiempo = (Load (3 + (10 x TiempoContador)) of (Key (Target unit of ability being cast)) from HashtableTiempo)
       Set YTiempo = (Load (5 + (10 x TiempoContador)) of (Key (Target unit of ability being cast)) from HashtableTiempo)
       Set PuntoTiempo = (Point(XTiempo, YTiempo))
                       Set AnguloTiempo = (Load (4 + (TiempoContador x 10)) of (Key (Picked unit)) from HashtableTiempo)
                       Unidad - Move (Picked unit) instantly to PuntoTiempo, facing AnguloTiempo degrees
                       Unidad - Set mana of (Picked unit) to ManaTiempo
                       Unidad - Cause (Triggering unit) to damage (Picked unit), dealing (90.00 + (100.00 x (Real((Level of (Ability being cast) for (Triggering unit)))))) damage of attack type Caos and damage type Universal[/gui]
A los héroes enemigos los dañamos, movemos, cambiamos angulo y seteamos maná

[gui]                   Otros: Acciones
                       Set ManaTiempo = (Load (1 + (TiempoContador x 10)) of (Key (Picked unit)) from HashtableTiempo)
                       Set VidaTiempo = (Load (2 + (TiempoContador x 10)) of (Key (Picked unit)) from HashtableTiempo)
                       Set XTiempo = (Load (3 + (10 x TiempoContador)) of (Key (Target unit of ability being cast)) from HashtableTiempo)
       Set YTiempo = (Load (5 + (10 x TiempoContador)) of (Key (Target unit of ability being cast)) from HashtableTiempo)
       Set PuntoTiempo = (Point(XTiempo, YTiempo))
                       Set AnguloTiempo = (Load (4 + (TiempoContador x 10)) of (Key (Picked unit)) from HashtableTiempo)
                       Unidad - Move (Picked unit) instantly to PuntoTiempo, facing AnguloTiempo degrees
                       Unidad - Set mana of (Picked unit) to ManaTiempo
                       Unidad - Set life of (Picked unit) to VidaTiempo[/gui]
Lo mismo para los héroes aliados, en este skill si interrumpo a los aliados, porque quiero.

[gui]         Otros: Acciones
               Set ManaTiempo = (Load (1 + (TiempoContador x 10)) of (Key (Picked unit)) from HashtableTiempo)
               Set VidaTiempo = (Load (2 + (TiempoContador x 10)) of (Key (Picked unit)) from HashtableTiempo)
               Unidad - Set mana of (Picked unit) to ManaTiempo
               Unidad - Set life of (Picked unit) to VidaTiempo[/gui]
Y el caster solo se ve afectado por este skill en su vida y maná


Descripción
Spoiler:
 



Es una simple y elegante forma de usar mi elegante y simple

sistema de tiempo :gafas:
Creo que no necesita explicación alguna.


Dejemos de lado mi hermoso sistema de tiempo un momento
👏 👏 
Gracias, gracias, yo también me amo

Un spell físico(o algo así)
Descripción:
Spoiler:
 

Init
Ustedes creen es mucho? Es solo el init ._.

Loop
Este es más cortito :cuernos: 

Explicación del Init:

[gui]Multiple FunctionsIf (All Conditions are True) then do (Then Actions) else do (Else Actions)
   Si: Condiciones
       (Target unit of ability being cast) Igual a Ninguna unidad
   Entonces: Acciones
       Set FNS_Punto = (Target point of ability being cast)
   Otros: Acciones
       Set FNS_Punto = (Position of (Target unit of ability being cast))[/gui]
Empezamos con un If para designar el punto inicial, puede ser el punto objetivo o la posición de la unidad objetivo.

[gui]Set FNS_Area = (100.00 + (125.00 x (Real((Level of (Ability being cast) for (Triggering unit))))))
Set FNS_Tiempo = (2.00 + (2.50 x (Real((Level of (Ability being cast) for (Triggering unit))))))
Set FNS_Grupo = (Units within FNS_Area of FNS_Punto matching (((Matching unit) is Una estructura) Igual a False))
Custom script:   call RemoveLocation(udg_FNS_Punto)[/gui]
Setear variables para nuestro skill, el área de efecto, el tiempo de duración y el grupo de unidades. Destruimos el punto para evitar leaks

[gui]Multiple FunctionsIf (All Conditions are True) then do (Then Actions) else do (Else Actions)
   Si: Condiciones
       (Number of units in FNS_Grupo) Mayor que o igual a 5
   Entonces: Acciones
       Set FNS_NumUnit = 5
        Do Multiple ActionsFor each (Integer A) from 1 to 5, do (Actions)
           Bucle: Acciones
               Custom script:   set udg_FNS_Target[bj_forLoopAIndex] = FirstOfGroup(udg_FNS_Grupo)
               Set FNS_PuntoTarget[(Integer A)] = (Position of FNS_Target[(Integer A)])
               Grupo de unidad - Remove FNS_Target[(Integer A)] from FNS_Grupo
               Set FNS_XTarget[(Integer A)] = (X of FNS_PuntoTarget[(Integer A)])
               Set FNS_YTarget[(Integer A)] = (Y of FNS_PuntoTarget[(Integer A)])
   Otros: Acciones
       Set FNS_NumUnit = (Number of units in FNS_Grupo)
        Do Multiple ActionsFor each (Integer A) from 1 to (Number of units in FNS_Grupo), do (Actions)
           Bucle: Acciones
               Custom script:   set udg_FNS_Target[bj_forLoopAIndex] = FirstOfGroup(udg_FNS_Grupo)
               Set FNS_PuntoTarget[(Integer A)] = (Position of FNS_Target[(Integer A)])
               Grupo de unidad - Remove FNS_Target[(Integer A)] from FNS_Grupo
               Set FNS_XTarget[(Integer A)] = (X of FNS_PuntoTarget[(Integer A)])
               Set FNS_YTarget[(Integer A)] = (Y of FNS_PuntoTarget[(Integer A)])
Custom script:   call DestroyGroup(udg_FNS_Grupo)[/gui]
El If es para evitar que las unidades afectadas sobrepasen las 5. Seteamos a cada unidad, de 1 a 5(o la cantidad de unidades en el grupo), su posición en X y en Y (Este spell es viejo y por eso está hecho de esta forma, que no es la más eficiente)
"FirstOfGroup" toma un grupo y te devuelve una unidad(la primera unidad agregada a ese grupo)
Se remueve la unidad del grupo para no buguear a "FirstOfGroup" Y destruimos grupo para evitar leaks.


[gui]Multiple FunctionsIf (All Conditions are True) then do (Then Actions) else do (Else Actions)
   Si: Condiciones
       FNS_NumUnit Igual a 1
   Entonces: Acciones
       Skip remaining actions[/gui]
He aquí lo pesado del spell. Primero un if, sí el numero de unidades afectadas en 1. No hace nada e_e

[gui]   Otros: Acciones
        Multiple FunctionsIf (All Conditions are True) then do (Then Actions) else do (Else Actions)
           Si: Condiciones
               FNS_NumUnit Igual a 2
           Entonces: Acciones
               Set FNS_Punto = (FNS_PuntoTarget[1] offset by ((Distance between FNS_PuntoTarget[1] and FNS_PuntoTarget[2]) / 2.00) towards (Angle from FNS_PuntoTarget[1] to FNS_PuntoTarget[2]) degrees)
               Unidad - Move FNS_Target[1] instantly to FNS_Punto
               Unidad - Move FNS_Target[2] instantly to FNS_Punto[/gui]
Si el número de unidades afectadas es 2. Creamos un punto en el medio de ambos con la ayuda de Point with polar offset.

[gui]           Otros: Acciones
               Set FNS_XPuntoMover[1] = ((FNS_XTarget[1] + (FNS_XTarget[2] + (FNS_XTarget[3] + (FNS_XTarget[4] + FNS_XTarget[5])))) / (Real(FNS_NumUnit)))
               Set FNS_YPuntoMover[1] = ((FNS_YTarget[1] + (FNS_YTarget[2] + (FNS_YTarget[3] + (FNS_YTarget[4] + FNS_YTarget[5])))) / (Real(FNS_NumUnit)))
               Set FNS_Punto = (Point(FNS_XPuntoMover[1], FNS_YPuntoMover[1]))
                Do Multiple ActionsFor each (Integer A) from 1 to FNS_NumUnit, do (Actions)
                   Bucle: Acciones
                       Unidad - Move FNS_Target[(Integer A)] instantly to FNS_Punto[/gui]
Si el número de unidades afectadas es mayor a 2. El punto a donde se moverán depende de una operación matemática sencilla.
Tiene valor en X y valor en Y y son iguales las fórmulas.
Valor medio = los valores de X sumados sobre la cantidad de valores X que sumemos (o sea, si tenemos 4 X sería: X1 + X2 + X3 + X4 / 4 )
Se aplica igual para Y


[gui]Custom script:   call RemoveLocation(udg_FNS_Punto)[/gui]
Antileaks e.e

[gui]Do Multiple ActionsFor each (Integer A) from 1 to FNS_NumUnit, do (Actions)
   Bucle: Acciones
       Custom script:   call RemoveLocation(udg_FNS_PuntoTarget[bj_forLoopAIndex])
       Tabla hash - Save Handle OfFNS_Target[(Integer A)] as (Integer A) of (Key (Triggering unit)) in HashFuerzaNuclear[/gui]
Destruimos los puntos para evitar leaks y guardamos cada target en la tabla hash.

[gui]Grupo de unidad - Add (Triggering unit) to FNS_Casters
Tabla hash - Save FNS_Tiempo as 0 of (Key (Triggering unit)) in HashFuerzaNuclear
Tabla hash - Save FNS_NumUnit as 6 of (Key (Triggering unit)) in HashFuerzaNuclear
Multiple FunctionsIf (All Conditions are True) then do (Then Actions) else do (Else Actions)
   Si: Condiciones
       (Number of units in FNS_Casters) Igual a 1
   Entonces: Acciones
       Detonador - Turn on FuerzaNuclear <gen>
   Otros: Acciones[/gui]
Agregamos caster al grupo, guardamos valores necesarios y encendemos el loop e.e

Explicación loop:
[gui]Multiple FunctionsIf (All Conditions are True) then do (Then Actions) else do (Else Actions)
   Si: Condiciones
       (Number of units in FNS_Casters) Mayor que (>) 0[/gui]
El deto loop es un if super gigante. Este if sirve para que solo corra si hay casters activos. Caso contrario se apaga

[gui]   Entonces: Acciones
       Grupo de unidad - Pick every unit in FNS_Casters and do (Actions)
           Bucle: Acciones
               Set FNS_Tiempo = (Load 0 of (Key (Picked unit)) from HashFuerzaNuclear)
               Set FNS_NumUnit = (Load 6 of (Key (Picked unit)) from HashFuerzaNuclear)
                Do Multiple ActionsFor each (Integer A) from 1 to FNS_NumUnit, do (Actions)
                   Bucle: Acciones
                       Set FNS_Target[(Integer A)] = (Load (Integer A) of (Key (Picked unit)) in HashFuerzaNuclear)[/gui]
Entonces, empezamos con las acciones de carga..

[gui]                Multiple FunctionsIf (All Conditions are True) then do (Then Actions) else do (Else Actions)
                   Si: Condiciones
                       FNS_Tiempo Mayor que o igual a 0.01[/gui]
Si el tiempo es mayor que 0
[gui]                   Entonces: Acciones
                        Multiple FunctionsIf (All Conditions are True) then do (Then Actions) else do (Else Actions)
                           Si: Condiciones
                               FNS_NumUnit Igual a 2
                           Entonces: Acciones
                               Set FNS_PuntoTarget[1] = (Position of FNS_Target[1])
                               Set FNS_PuntoTarget[2] = (Position of FNS_Target[2])
                               Set FNS_Punto = (FNS_PuntoTarget[1] offset by ((Distance between FNS_PuntoTarget[1] and FNS_PuntoTarget[2]) / 2.00) towards (Angle from FNS_PuntoTarget[1] to FNS_PuntoTarget[2]) degrees)[/gui]
Entonces, hacemos otro if, Si NumUnit igual a 2. Seteamos el punto medio
[gui]                                Do Multiple ActionsFor each (Integer A) from 1 to FNS_NumUnit, do (Actions)
                                   Bucle: Acciones
                                       Set FNS_Angulo[(Integer A)] = (Angle from FNS_PuntoTarget[(Integer A)] to FNS_Punto)
                                       Set FNS_PuntoMover[(Integer A)] = (FNS_PuntoTarget[(Integer A)] offset by ((Distance between FNS_Punto and FNS_PuntoTarget[(Integer A)]) / 10.00) towards FNS_Angulo[(Integer A)] degrees)
                                       Set FNS_XPuntoMover[(Integer A)] = (X of FNS_PuntoMover[(Integer A)])
                                       Set FNS_YPuntoMover[(Integer A)] = (Y of FNS_PuntoMover[(Integer A)])
                                       Custom script:   call SetUnitX(udg_FNS_Target[bj_forLoopAIndex], udg_FNS_XPuntoMover[bj_forLoopAIndex)])
                                       Custom script:   call SetUnitY(udg_FNS_Target[bj_forLoopAIndex], udg_FNS_YPuntoMover[bj_forLoopAIndex])
                                       Custom script:   call RemoveLocation(udg_FNS_PuntoMover[bj_forLoopAIndex])
                                       Custom script:   call RemoveLocation(udg_FNS_PuntoTarget[bj_forLoopAIndex])[/gui]
Después, hacemos un loop (que irá de 1 a 2 nada más) y los atraemos hacia el punto medio (Ahora que veo esto, no sé porque lo hice así, debería atraer más..


[gui]                           Otros: Acciones
                                Do Multiple ActionsFor each (Integer A) from 1 to FNS_NumUnit, do (Actions)
                                   Bucle: Acciones
                                       Set FNS_PuntoTarget[(Integer A)] = (Position of FNS_Target[(Integer A)])
                                       Set FNS_XTarget[(Integer A)] = (X of FNS_PuntoTarget[(Integer A)])
                                       Set FNS_YTarget[(Integer A)] = (Y of FNS_PuntoTarget[(Integer A)])
                               Set FNS_XPuntoMover[1] = ((FNS_XTarget[1] + (FNS_XTarget[2] + (FNS_XTarget[3] + (FNS_XTarget[4] + FNS_XTarget[5])))) / (Real(FNS_NumUnit)))
                               Set FNS_YPuntoMover[1] = ((FNS_YTarget[1] + (FNS_YTarget[2] + (FNS_YTarget[3] + (FNS_YTarget[4] + FNS_YTarget[5])))) / (Real(FNS_NumUnit)))
                              Set FNS_Punto = (Point(FNS_XPuntoMover[1], FNS_YPuntoMover[1]))[/gui]
Aquí es igual que en el anterior, setamos punto medio con la fórmula
[gui]                                Do Multiple ActionsFor each (Integer A) from 1 to FNS_NumUnit, do (Actions)
                                   Bucle: Acciones
                                       Set FNS_Angulo[(Integer A)] = (Angle from FNS_PuntoTarget[(Integer A)] to FNS_Punto)
                                       Set FNS_PuntoMover[(Integer A)] = (FNS_PuntoTarget[(Integer A)] offset by ((Distance between FNS_Punto and FNS_PuntoTarget[(Integer A)]) / 10.00) towards FNS_Angulo[(Integer A)] degrees)
                                       Set FNS_XPuntoMover[(Integer A)] = (X of FNS_PuntoMover[(Integer A)])
                                       Set FNS_YPuntoMover[(Integer A)] = (Y of FNS_PuntoMover[(Integer A)])
                                       Custom script:   call SetUnitX(udg_FNS_Target[bj_forLoopAIndex], udg_FNS_XPuntoMover[bj_forLoopAIndex])
                                       Custom script:   call SetUnitY(udg_FNS_Target[bj_forLoopAIndex], udg_FNS_YPuntoMover[bj_forLoopAIndex])
                                       Custom script:   call RemoveLocation(udg_FNS_PuntoMover[bj_forLoopAIndex])
                                       Custom script:   call RemoveLocation(udg_FNS_PuntoTarget[bj_forLoopAIndex])[/gui]
Luego en un loop, movemos a cada unidad al igual que en el anterior.

[gui]                   Otros: Acciones
                       Tabla hash - Clear all child hashtables of child (Key (Picked unit)) in HashFuerzaNuclear
                       Grupo de unidad - Remove (Picked unit) from FNS_Casters[/gui]
Cuando el tiempo baja a 0.00 el spell termina

[gui]               Tabla hash - Save (FNS_Tiempo - 0.04) as 0 of (Key (Picked unit)) in HashFuerzaNuclear[/gui]
Reducimos el tiempo

[gui]   Otros: Acciones
       Detonador - Turn off (This trigger)[/gui]
Cuando no quedan casters activos el deto se apaga.

Simplemente. Sin comentarios 👏 👏 👏 


Ahora tenemos, OTRO SISTEMA! :epa: :epa: 

Descripción:
Spoiler:
 


Es pequeño y hermoso .3

[gui]Custom script:   if CountUnitsInGroup(udg_grupoknockback) > 0 then[/gui]
Si la cantidad de unidades en el grupo del knockback es mayor que 0 entonces

[gui]Custom script:   call GroupAddGroup( udg_grupoknockback, udg_grupoloop )[/gui]
Esta es la única BJ que quedó en el sistema, es para agregar al grupo del loop todas las unidades del grupo knockback, lo correcto sería usar ForGroup, pero no sé declarar funciones en GUI

[gui]Custom script:   loop[/gui]
Iniciamos un loop e.e

[gui]Custom script:   set udg_knockbacked = FirstOfGroup(udg_grupoloop)[/gui]
Tomamos a la primera unidad del grupoloop

[gui]Custom script:   call GroupRemoveUnit(udg_grupoloop, udg_knockbacked)[/gui]
La removemos del grupo para evitar bugs (Si no la removemos tomaremos la misma unidad infinitamente y nos crashea el juego)

[gui]Custom script:   exitwhen udg_knockbacked == null[/gui]
Esto quiere decir que el loop terminará cuando knockbacked sea igual a Ninguna unidad

[gui]Custom script:   set udg_tiempoknockback = ( LoadReal(udg_HashKnockBack, GetHandleId(udg_knockbacked), 2) - 0.04 )[/gui]
Seteamos el tiempo, cargamos el valor que es tiempo en nuestra tabla hash y le reducimos 0.04

[gui]Custom script:    call SaveReal( udg_HashKnockBack, GetHandleId(udg_knockbacked), 2, udg_tiempoknockback )[/gui]
Guardamos el tiempo

[gui]Set puntoactualkb = (Position of knockbacked)[/gui]
El punto donde está knockbacked

[gui]Custom script:   set udg_angleknockback = LoadReal(udg_HashKnockBack, GetHandleId(udg_knockbacked), 3)[/gui]
Cargamos el ángulo

[gui]Set puntoknockback = (puntoactualkb offset by 12.00 towards angleknockback degrees)[/gui]
Hacia donde moveremos la unidad e.e

[gui]Custom script:   if udg_tiempoknockback > 0.00 then[/gui]
Otro if, si el tiempo es mayor a 0 entonces..

[gui]Unidad - Move knockbacked instantly to puntoknockback[/gui]
Movemos la unidad provocando que se interrumpa gracias a esta acción .3

[gui]Custom script:   else
Custom script:   call FlushChildHashtable(udg_HashKnockBack, GetHandleId(udg_knockbacked) )
Custom script:   call GroupRemoveUnit(udg_grupoknockback, udg_knockbacked)
Custom script:   endif[/gui]
Si no, limpiamos nuestra tabla hash y removemos a knockbacked del grupo. Y terminamos el if

[gui]Custom script:   endloop[/gui]
Terminamos loop e.e

[gui]Custom script:   else
Detonador - Turn off (This trigger)
Custom script:   endif[/gui]
Si recuerdan el primer if que hicimos, no lo cerramos todavía. Si ese primer if es falso, apagamos el detonador, cerramos el if y el deto se termina


Ahora vamos a ver nuestro knockback en acción :gafas:
Tiene 2 ejemplos de acción en el mapa tutorial, pero uno está hecho con integers y no es relevante al tutorial.

Pero tenemos un ejemplo de un pasivo :DD





Lo único que hace el init es agregar el evento al detonador

[gui]Set PuntoKOD1 = (Position of (Triggering unit))[/gui]
[gui]Set PuntoKOD2 = (Position of (Damage source))[/gui]
Punto de la unidad dañada y la unidad dañante

[gui]Multiple FunctionsIf (All Conditions are True) then do (Then Actions) else do (Else Actions)
   Si: Condiciones
       (Distance between PuntoKOD1 and PuntoKOD2) Menor que o igual a (200.00 + (50.00 x (Real((Level of KnockOnDamage  for (Triggering unit))))))[/gui]
Un if, para evitar que se activa desde distancia muy elevadas, hago esto porque quiero

   [gui]Entonces: Acciones
       Efecto especial - Create a special effect attached to the chest of (Triggering unit) using Abilities\Spells\Items\SpellShieldAmulet\SpellShieldCaster.mdl
       Efecto especial - Destroy (Last created special effect)[/gui]
Entonces, creamos un efecto en el "pecho" de triggering unit con el modelo de la defensa mágica. Destruimos para evitar leaks

       [gui]Set tiempoknockback = (0.30 x (Real((Level of KnockOnDamage  for (Triggering unit)))))
       Set angleknockback = (Angle from PuntoKOD1 to PuntoKOD2)
       Set knockbacked = (Damage source)
       Custom script:   if CountUnitsInGroup(udg_grupoknockback) == 0 then
       Detonador - Turn on Knockback <gen>
      Custom script:   endif[/gui]
Ahora aplicamos nuestro sistema de knockback. Primero seteamos el tiempo del knockback, después el ángulo(Se suele utilizar el ángulo desde el punto fuente hacia el punto objetivo para que la unidad se aleje), seteamos la unidad y en un if, si la cantidad de unidades en el grupo knockback es 0, encendemos el detonador del knockback

       [gui]Custom script:   call GroupAddUnit(udg_grupoknockback, udg_knockbacked)
       Custom script:    call SaveReal( udg_HashKnockBack, GetHandleId(udg_knockbacked), 2, udg_tiempoknockback )
       Custom script:    call SaveReal( udg_HashKnockBack, GetHandleId(udg_knockbacked), 3, udg_angleknockback )[/gui]
Agregamos la unidad al grupo y guardamos los valores de ángulo y tiempo en nuestra unidad.

Y con este knockback terminamos los ejemplos de GUI de este tuto.

Sin embargo, hice un sistema utilizando tablas hash que asocia el Id del item "arma" con su número total de cargas y su Item "cargador" he aquí, el link
http://www.worldofeditors.net/t10-sistema-sistema-de-municion
Pienso yo es útil para aprender .3



Última edición por Marcos_M el Dom Oct 13, 2013 4:01 pm, editado 3 veces
Volver arriba Ir abajo
Marcos_M

avatar


Barra de Salud : Su salud está al 100% - Este usuario no ha recibido infracciones

Mensajes Mensajes : 3019
Reputación Reputación : 500
Monedas de oro : 9283
Monedas de Platino : 0

Inventario :



Mensaje(#) Tema: Re: Todo lo que necesites saber sobre Tablas Hash (o no?) • Jue Jul 25, 2013 9:59 pm

b. En JASS:
Las tablas hash en JASS son más usadas por mí que en GUI, porque son lo que se usar Razz

Descripción:
Spoiler:
 

[jass]function InitSistemaHabis_Actions takes nothing returns nothing
   local item i
   local integer id
   set i = CreateItem('I000', 0,0)
   set id = GetItemTypeId(i)
   call SaveInteger(udg_TablaItems, id,StringHash("Spell") , 'ACss')
   call SaveInteger(udg_TablaItems, id,StringHash("ItemBlock1"), 'I001')
   call SaveInteger(udg_TablaItems, id,StringHash("ItemBlock2"), 'I002')
   call RemoveItem(i)
//=======================================================================================
   set i = CreateItem('I001', 0,0)
   set id = GetItemTypeId(i)
   call SaveInteger(udg_TablaItems, id,StringHash("Spell") , 'ACfb')
   call SaveInteger(udg_TablaItems, id,StringHash("ItemBlock1"), 'I000')
   call SaveInteger(udg_TablaItems, id,StringHash("ItemBlock2"), 'I002')
   call RemoveItem(i)
//=======================================================================================
   set i = CreateItem('I002', 0,0)
   set id = GetItemTypeId(i)
   call SaveInteger(udg_TablaItems, id,StringHash("Spell") , 'ACfs')
   call SaveInteger(udg_TablaItems, id,StringHash("ItemBlock1"), 'I001')
   call SaveInteger(udg_TablaItems, id,StringHash("ItemBlock2"), 'I000')
   call RemoveItem(i)
//=======================================================================================
   set i = null
endfunction

//===========================================================================
function InitTrig_InitSistemaHabis takes nothing returns nothing
   local trigger t = CreateTrigger(  )
   call TriggerRegisterTimerEvent( t, 1.00, false )
   call TriggerAddAction( t, function InitSistemaHabis_Actions )
   set t = null
endfunction[/jass]
Aquí se registran los items



[jass]function Trig_Comprar_Habi_Conditions takes nothing returns boolean
   if GetPlayerTechMaxAllowed(GetOwningPlayer(GetBuyingUnit()), GetItemTypeId(GetSoldItem())) == 0 then
       call SetPlayerState(GetOwningPlayer(GetBuyingUnit()), PLAYER_STATE_RESOURCE_LUMBER, ( GetPlayerState(GetOwningPlayer(GetBuyingUnit()), PLAYER_STATE_RESOURCE_LUMBER) + 1 ) )
       call BJDebugMsg("Ya compraste una habilidad!!")
   endif
   return GetItemType(GetSoldItem()) == ITEM_TYPE_POWERUP and GetPlayerTechMaxAllowed(GetOwningPlayer(GetBuyingUnit()), GetItemTypeId(GetSoldItem())) > 0
endfunction

function Trig_Comprar_Habi_Actions takes nothing returns nothing
   local unit u = GetBuyingUnit()
   local item i = GetSoldItem()
   local integer id = GetItemTypeId(i)
   local integer Spell = LoadInteger(udg_TablaItems, id, StringHash("Spell"))
   local integer ItemBlock1 = LoadInteger(udg_TablaItems, id, StringHash("ItemBlock1"))
   local integer ItemBlock2 = LoadInteger(udg_TablaItems, id, StringHash("ItemBlock2"))
   local integer Num = GetUnitAbilityLevel(u, Spell)
   local player p = GetOwningPlayer(u)
   call SetPlayerTechMaxAllowed(p, ItemBlock1, 0)
   call SetPlayerTechMaxAllowed(p, ItemBlock2, 0)
   if Num == 0 then
       call UnitAddAbility(u, Spell)
   else
       if Num < 3 then
           call SetUnitAbilityLevel(u, Spell, Num + 1 )
       else
           call SetPlayerState(GetOwningPlayer(GetBuyingUnit()), PLAYER_STATE_RESOURCE_LUMBER, ( GetPlayerState(GetOwningPlayer(GetBuyingUnit()), PLAYER_STATE_RESOURCE_LUMBER) + 1 ) )
           call BJDebugMsg("Esta habilidad ya está en nivel máximo!")
       endif
   endif
   set u = null
   set i = null
   set p = null
endfunction

//===========================================================================
function InitTrig_Comprar_Habi takes nothing returns nothing
   local trigger t = CreateTrigger(  )
   call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SELL_ITEM )
   call TriggerAddCondition( t, Condition( function Trig_Comprar_Habi_Conditions ) )
   call TriggerAddAction( t, function Trig_Comprar_Habi_Actions )
   set t = null
endfunction[/code]Y esto hace la magia..

Expliquemos como funciona esto

Código:
function InitSistemaHabis_Actions takes nothing returns nothing
    local item i
    local integer id
    set i = CreateItem('I000', 0,0)
    set id = GetItemTypeId(i)
    call SaveInteger(udg_TablaItems, id,StringHash("Spell") , 'ACss')
    call SaveInteger(udg_TablaItems, id,StringHash("ItemBlock1"), 'I001')
    call SaveInteger(udg_TablaItems, id,StringHash("ItemBlock2"), 'I002')
    call RemoveItem(i)
Así empezamos en el init. Declaramos las 2 variables que usaremos, un item y un integer
Seteamos el item y lo creamos. Y seteamos el rawcode en el ID.
Ahora, pueden setear directamente el rawcode de su item y guardar ahí, pero yo lo hice así a modo de pequeño preload .3
Y guardamos en la tabla hash, el spell y los 2 items a bloquear.
Removemos el item y eso es todo. Tu item está registrado e_e
Ahora veremos el trigger de la magia.

[code]function Trig_Comprar_Habi_Conditions takes nothing returns boolean
   if GetPlayerTechMaxAllowed(GetOwningPlayer(GetBuyingUnit()), GetItemTypeId(GetSoldItem())) == 0 then
       call SetPlayerState(GetOwningPlayer(GetBuyingUnit()), PLAYER_STATE_RESOURCE_LUMBER, ( GetPlayerState(GetOwningPlayer(GetBuyingUnit()), PLAYER_STATE_RESOURCE_LUMBER) + 1 ) )
       call BJDebugMsg("Ya compraste una habilidad!!")
   endif
   return GetItemType(GetSoldItem()) == ITEM_TYPE_POWERUP and GetPlayerTechMaxAllowed(GetOwningPlayer(GetBuyingUnit()), GetItemTypeId(GetSoldItem())) > 0
endfunction[/jass]

Analicemos las condiciones..
El primer if es para evitar que pierdas la madera gastada si compras un item bloqueado.
Y lo importante en una condición es el "return" pues en base en eso nos devolverá una booleana.
En este caso las condiciones son, El item vendido debe ser Potenciador y El máximo de items del ID del item vendido, debe ser mayor a 0

[jass]function Trig_Comprar_Habi_Actions takes nothing returns nothing
   local unit u = GetBuyingUnit()
   local item i = GetSoldItem()
   local integer id = GetItemTypeId(i)
   local integer Spell = LoadInteger(udg_TablaItems, id, StringHash("Spell"))
   local integer ItemBlock1 = LoadInteger(udg_TablaItems, id, StringHash("ItemBlock1"))
   local integer ItemBlock2 = LoadInteger(udg_TablaItems, id, StringHash("ItemBlock2"))
   local integer Num = GetUnitAbilityLevel(u, Spell)
   local player p = GetOwningPlayer(u)[/jass]
Seteamos las variables a usar. La unida compradora, el item vendido, el id del item vendido, cargamos los items a bloquear y el spell comprado, Num nos servirá más adelante y el jugador comprador

[jass]  call SetPlayerTechMaxAllowed(p, ItemBlock1, 0)
   call SetPlayerTechMaxAllowed(p, ItemBlock2, 0)[/jass]
Bloqueamos los items para el jugador

[jass]   if Num == 0 then
       call UnitAddAbility(u, Spell)
   else
       if Num < 3 then
           call SetUnitAbilityLevel(u, Spell, Num + 1 )
       else
           call SetPlayerState(GetOwningPlayer(GetBuyingUnit()), PLAYER_STATE_RESOURCE_LUMBER, ( GetPlayerState(GetOwningPlayer(GetBuyingUnit()), PLAYER_STATE_RESOURCE_LUMBER) + 1 ) )
           call BJDebugMsg("Esta habilidad ya está en nivel máximo!")
       endif
   endif[/jass]
Este if nos sirve para designar, si el nivel de Spell para u es 0, entonces le agregamos la habi
Si es desigual a 0 (o mayor, es imposible tener level -1 en una habi hasta donde yo sé). Le subimos el nivel a 1 a la spell. Si el nivel de la habilidad es 3. No puedes comprar el item y seteamos la madera +1 para evitar que pierdas recursos

[jass]   set u = null
   set i = null
   set p = null[/jass]
Antileaks e.e


Ese fue el pequeño sistema .3

Ahora un par de spells subidos al foro, pero revisarlos más a fondo será útil para aprender
Aquí solo pasaré a colocar descripción porque toda la explicación está en el mapa tutorial e.e

Descripción:
Spoiler:
 

Descripción:
Spoiler:
 


Por último, recuerden copiar el Faux a su código personalizado, me dijeron que tengo uno desactualizado así que si un mod tiene el actualizado lo coloca aquí y me avisa que cambios debo hacer :c

Spoiler:
 


Truquito para GUI .3
Si hacemos memoria, mencioné que había una lista de variables incargables con tabla hash en GUI. Para eso existen acciones en JASS que podemos usar para cargar y guardar.

Estas variables podemos traducir a integer o string
Buff (Integer)
Forma de Terreno (1= Cuadrado, 0= Círculo)
Habilidad (Integer)
Orden (String)
Tipo de Terreno (Integer)
Tipo de Destructible (Integer)
Tipo de Objeto (Integer)
Tipo de Rayo (String)
Tipo técnico (Integer)
Tipo de unidad (Integer)

Así que si necesitan guardar y cargar alguno de estos, hacen lo siguiente:
Crean un detonador vacío y colocan su variable a traducir:
variable Set Habi = Andar del viento
variable Set Orden = (Order(windwalk))

En este caso tenemos andar del viento y su orden. Van a Editar y luego Convertir a texto personalizado y les quedará convertidas en esto
[jass]   set udg_Habi = 'AOwk'
   set udg_Orden = "windwalk"[/jass]

Eliminen la función de la orden para que quede
[jass]set udg_Orden = "windwalk"[/jass]

Ahora en una variable de integer y una de string. Respectivamente, van a guardar sus valores.

[gui]Custom script:   set udg_Integer = 'AOwk'
Set String = windwalk[/gui]
Y ya tienen su string y su orden que pueden ser guardadas y cargadas desde GUI sin ningún problema. Pero, para poder utilizarlas necesitarán un poco de custom script. En este ejemplo provocaremos que la unidad utilice andar del viento y se la removeremos automaticamente.

[gui]Set Unidad = Ninguna Unidad
Custom script:   set udg_Integer = 'AOwk'
Set String = windwalk
Custom script:   call UnitAddAbility(udg_Unidad, udg_Integer)
Custom script:   call IssueImmediateOrder(udg_Unidad, udg_Cadena)
Custom script:   call UnitRemoveAbility(udg_Unidad, udg_Integer)[/gui]
Ustedes deciden que poner en Unidad, yo puse ninguna por falta de innovación, pero este ejemplo simple sirve para ilustrar como utilizar strings e integers para órdenes y habilidades respectivamente. Guardar y cargarlas lo pueden hacer desde GUI y creo no necesita expliación, esto solo es un ejemplo de lo que pueden hacer. Si quieren saber que string deben utilizar para sus habilidades, pueden transformar a Texto personalizado la acción de GUI y entre comillas aparecerá la orden ("rainoffire" por ejemplo)

y la acción de orden solo funciones con accciones inmediatas en este caso. Para lanzar a punto o a unidad se utiliza

[gui]Custom script:   call IssueTargetOrder( udg_Unidad, "dispel", null )[/gui]
Sirve para usar una orden con objetivo una unidad, la primera unidad es a quien ordenaremos, la string es la orden, y la segunda unidad(null[Ninguna] en el ejemplo) es a quien lanzamos "dispel"(disipar)

[gui]Custom script:   call IssuePointOrderLoc( udg_Unidad, "blizzard", udg_Punto )[/gui]
Aquí es practicamente lo mismo, solo que colocamos el punto objetivo en lugar que la unidad objetivo. Simple verdad?

También, si no queremos complicarnos con los custom scripts (para los ordenes esto no funciona) podemos hacer esto:
Partimos de unas variables normales(Será ejemplo random así que solo no tiene utilidad alguna)

variable Set TipoRayo = Robar vida
variable Set TipoDeTerreno = Felwood - Roca
Traducimos a:
[jass]   set udg_TipoRayo = "DRAL"
   set udg_TipoDeTerreno = 'Crck'[/jass]

Y en GUI las colocamos como
[gui]Set String = DRAL
Custom script:   set udg_Integer = 'Crck'[/gui]
Guardan o les hacen lo que quieran. Pero al momento de reusarlas las transformamos a Tipo de Rayo y Tipo de Terreno nuevamente así

26 Custom script:   set udg_TipoRayo = udg_String
26 Custom script:   set udg_TipoDeTerreno = udg_Integer
Y ya pueden usarlas normalmente en GUI e_e
Conversión y reconversión


Y un último consejo, si miran mi spell "Fuerza Nuclear" se guarda todo en el caster, les digo que mejor que guardar las cosas en el caster, es crear una unidad dummy y guardar todo ahí, porque si guardas en el caster hay posibilidades de sobreescribirse, es un error mío por haberlo aprendido así y por ser un skill viejo, sepan disculparme n.n

Terminamos el tutorial, con nuestro mapa tutorial, antes
quiero decirles. Gracias por leer, y se agradecerá todos los MP
que manden y la rep que den(a menos que sea negativa e_e)
Espero que no sean trolls y miren mi tutorial, porque me costó
mucho y eviten los comentarios que marque arriba porque de nada me
sirven solo ocupan espacio en el post. Por supuesto, las preguntas
están totalmente aceptadas


http://www.epicwar.com/maps/231285/
SOLO LOS SPELLS DE JASS ESTAN COMENTADOS, SI QUIERES ENTENDER ESTE TUTORIAL EL MAPA TUTORIAL NO BASTA


Última edición por Marcos_M el Dom Oct 13, 2013 4:06 pm, editado 1 vez
Volver arriba Ir abajo
ILoGy
Caballero
avatar


Barra de Salud : Su salud está al 100% - Este usuario no ha recibido infracciones

Mensajes Mensajes : 405
Reputación Reputación : 72
Monedas de oro : 2433
Monedas de Platino : 2

Inventario :



Mensaje(#) Tema: Re: Todo lo que necesites saber sobre Tablas Hash (o no?) • Jue Ago 01, 2013 12:08 am

Bueno, es brutal este tutorial, te pasaste, me falta leerlo, la verdad me da un poco de pereza, pero seguro que si surge una duda sobre el tema, ya se donde resolverla, excelente tuto marco, uno de master!! Wink  + rep
Volver arriba Ir abajo
adrian592
Aprendiz


Barra de Salud : Su salud está al 100% - Este usuario no ha recibido infracciones

Mensajes Mensajes : 26
Reputación Reputación : 0
Monedas de oro : 76
Monedas de Platino : 0

Inventario :



Mensaje(#) Tema: Re: Todo lo que necesites saber sobre Tablas Hash (o no?) • Mar Ago 05, 2014 8:46 pm

Aca hice algunos integer, pero quice poner un "rawcode" de objeto dentro de otro "rawcode" de destructible, me quedo algo asi

[img][/img]

mi pregunta es, como sigo ahora para que pueda a llegar a funcionar?
Volver arriba Ir abajo
Trigger.edge

avatar


Barra de Salud : Este usuario es invulnerable ¿Será que es fiel a las normas?

Mensajes Mensajes : 978
Reputación Reputación : 109
Monedas de oro : 1243
Monedas de Platino : 0

Inventario :
Cetro del Rey Armadura Mágica Daga Mística


Mensaje(#) Tema: Re: Todo lo que necesites saber sobre Tablas Hash (o no?) • Miér Ago 06, 2014 3:07 pm

Wow! Este si que es el Mega tutorial del siglo Marcos!  Very Happy +rep
Volver arriba Ir abajo
xoloems
Iniciado


Barra de Salud : Su salud está al 100% - Este usuario no ha recibido infracciones

Mensajes Mensajes : 10
Reputación Reputación : 0
Monedas de oro : 10
Monedas de Platino : 0

Inventario :



Mensaje(#) Tema: Re: Todo lo que necesites saber sobre Tablas Hash (o no?) • Vie Nov 13, 2015 4:52 am

muy buen aporte affraid
Volver arriba Ir abajo
Contenido patrocinado




Mensaje(#) Tema: Re: Todo lo que necesites saber sobre Tablas Hash (o no?) •

Volver arriba Ir abajo
 

Todo lo que necesites saber sobre Tablas Hash (o no?) •

Ver el tema anterior Ver el tema siguiente Volver arriba 
Página 1 de 1.

Permisos de este foro:No puedes responder a temas en este foro.
Warcraft III - WorldEditor :: Academia :: Area GUI-