Welcome to TiddlyWiki created by Jeremy Ruston, Copyright © 2007 UnaMesa Association
Cada jugador determina el [[rol|Roles]] de su personaje. Para ello pueden hacerse ajustes similares a los hechos en el [[paso anterior|9no Paso]].
Cada jugador equipa a su personaje con equipo apropiado a su Riqueza, Raza y Rol.
Se tradujo los artículos de los [[Engendros de Dragón Azul|Engendro de Dragón Azul]] y los [[Draconianos]].
*Se incluyeron algunas [[Razas]] y [[Roles]] nuevos. Hace falta poner mi aporte personal en las reglas, hacer traducción o paráfrasis al español, y por supuesto hacer explícito agradecimiento a los autores de los textos.
Se hizo enlace en la sección de [[Roles]] a varios roles, aunque no han sido traducidos al español.
*Se tradujo el artículo de los [[Gnolls]]. Hace falta una imágen hecha por un fan, para quitar la que he puesto, que sospecho es de algún libro oficial. Se aceptan sugerencias.
*Se incluyó una imágen al artículo de los [[Bakalis|Bakali]].
Creé el Rol del [[Heroe de Capa-y-espada]] (//swashbuckler//). También fue acomodado el formato e idoma de algunos pocos roles.
*Se avanzó en la traducción de varias secciones de [[Era de los Mortales]]
*Se incluyeron imágenes en varios artículos, procurando en la medida de lo posible, hacer el reconocimiento al autor.
*Se empezaron a cargar en la página las pericias del sistema de pericias múltiples
Traducción/Redacción de:
*[[Acciones Avanzadas en Combate]]
*[[Secuencia de Combate]]
*[[Rango de Combate]]
*[[Ayuda]]
*[[Navegación en la SAGApedia]]
*[[TiddlyWiki]]
*[[SAGApedia]]
Cada jugador toma 12 cartas del Mazo del Destino
*Se tradujo y simplificó el artículo sobre los [[Bakali]]
Se completó la información de las [[Razas]] básicas
*Se elaboró el artículo de [[Carta de Triunfo]], de [[Desgracia]] y el de las [[pintas|Pinta de las cartas]].
*Se empezó a crear los artículos para [[Convertir estadísticas de AD&D a SAGA]].
*Se empezó a crear una tabla con las [[Acciones en Combate]].
*Se crearon artículos para explicar sobre la [[Lectura de las cartas]] y el [[Aura de una carta]].
*Coloqué información sobre [[Armas Tribales]]
*Se incluyó el Rol de [[Arquero]]
*Se tradujo, parafraseó y resumió la información respecto al rol de [[Elfo Moldeador de Madera]].
*Se puso la etiqueta [[Elfos]] al Tiddler de [[Roles Élficos]], para facilitar la navegación.
Se resumió la información y se tradujo el artículo sobre [[Elfos Acuáticos]].
Cada jugador escoge dos cartas correspondientes a la personalidad:
*Una para el [[Comportamiento]] (//Demeanor//), o lo que proyecta
*Una para la [[Naturaleza]] (//Nature//), o lo que motiva internamente al personaje
Se recomienda usar las cartas con menor valor en este paso, o cartas de [[Pinta de Dragones]]. Estas son de menos utilidad en los pasos posteriores de la creación del personaje.
*Se incluyó en la sección de [[Magia]] la tabla necesaria para el [[Diseño de Hechizos]]
Cada jugador escoge una carta que representa la cantidad de aventuras que un héroe ha experimentado. También determinará la cantidad de cartas que habrá en la Mano del jugador y la reputación.
Quests
|!Aventuras|!Mano del Destino|!Reputación|
|0|1 carta|Desconocido|
|1|2 cartas|Principiante|
|2-3|3 cartas|Novicio|
|4-6|4 cartas|Aventurero|
|7-10|5 cartas|Campeón|
|11-15|6 cartas|Maestro|
|16-21|7 cartas|Héroe|
|22-28|8 cartas|Leyenda|
|29 +|9 cartas|Arquetipo|
De alguna forma, la "pinta" de la carta utilizada para determinar la cantidad de aventuras, refleja el tipo de papel que jugó el personaje en sus aventuras, el tipo de aventuras en las que se vio involucrado, o el tipo de reputación que ganó al hacerlas ({{{regla de la casa}}}).
Cada jugador escoge una carta que determina la [[Riqueza]] del personaje:
|!Riqueza|!Estatus Social|
|1|Esclavo|
|2|Campesino|
|3|Hombre Libre|
|4|Mercader|
|5|Agremiado|
|6|Terrateniente|
|7|Aristocracia|
|8|Nobleza|
|9+|Realeza|
La "pinta" de la carta utilizada, de alguna forma refleja la forma en que el Héroe obtuvo su riqueza, o lo que esta ha representado en su vida ({{{regla de la casa}}}).
Es útil utilizar una carta de Dragones.
Cada Héroe debe asignar cada una de las 8 cartas que quedan, a las [[Habilidades]], tomando en cuenta la pinta de la carta asignada:
*Físicas
**Coordinación
***Agilidad (Agi)
***Destreza (Dex)
**Fortaleza Física
***Fuerza (Str)
***Resistencia (End)
*Mentales
**Intelectuales
***Razonamiento (Rea)
***Percepción (Per)
**Esencia
***Espíritu (Spi)
***Presencia (Pre)
''Nota'': En SAGA...
*Agilidad (Agi) es utilizada casi siempre para evitar ataques hechos usando Destreza (Dex), casi siempre ataques de rango.
*Resistencia (End) es utilizada casi siempre para bloquear o resistir ataques hechos usando Fuerza (Str), casi siempre en luchas cuerpo-a-cuerpo.
*Percepción (Per) es utilizada casi siempre para bloquear o resistir ataques mágicos utilizando [[Hechicería]], y por lo tanto, Razonamiento (Rea).
*Presencia (Pre) es utilizada casi siempre para resistir ataques mágicos utilizando [[Misticismo]], y por lo tanto Espíritu (Spi).
*En general, Agilidad (Agi) y Percepción (Per) son utilizadas en {{{Reglas de la casa}}} para hacer el chequeo de iniciativa.
Para saber cuál es el [[código de la habilidad|Código de Habilidades]], basta con comparar las "pintas" de las cartas, con la habilidad en la que se han colocado.
*Si se usó una carta cuya pinta corresponde a la [[Habilidad]] a la que se asigna, recibe un código de "A".
*Si usa una carta cuya pinta es de la misma sub-categoría que la [[Habilidad]] a la que se asigna, recibe un código de "B". Ejemplo: Usar una carta de Flechas para colocar en Agilidad, siendo que ambas están en la sub-categoría de Coordinación, hará que el código de Agilidad sea "B".
*Si usa una carta cuya pinta está en la misma categoría general que la [[Habilidad]] a la que se asigna, recibe un código de "C". Ejemplo: Usar una carta de Flechas para colocar en Resistencia (End), siendo que ambas pertenecen a la misma categoría, hará que el código de Resistencia sea "C".
*Si usa una carta cuya pinta no está en la misma categoría general que la [[Habilidad]] a la que se asigna, recibe un código de "D".
*Por último, si utiliza una carta de Dragones, recibe un código automático de "X".
Quienes usan magia deben escoger sus escuelas de [[Hechicería]] y/o esferas de [[Misticismo]]. Si los códigos de las habilidades, podría ser tanto místico como hechicero, y tener tanto escuelas como esferas mágicas.
Abajo se listan los tipos de magia:
*[[Escuelas de Hechicería]]
*[[Esferas de Misticismo]]
Este también es el momento para escoger los sentidos agudos o deficientes, en caso de tener código de Percepción diferente de "C".
[>img[Arte por Mandrak en http://fx.worth1000.com|http://rookery.s3.amazonaws.com/884000/884034_35fd_625x1000.jpg]]
Cada jugador determina cuántos puntos de magia posee.
*Si es Hechicero, es el cuadrado de su Razonamiento
*Si es Místico, es el cuadrado de su Espíritu
*Si es ambas cosas, tiene dos fuentes de puntos de magia diferentes e independientes
Los puntos de magia se regeneran uno por hora, sin importar el tipo de magia.
Si un hechicero o místico duerme completo, recupera la totalidad de sus puntos de magia.
Opcionalmente, puede calcularse los puntos de magia de forma diferente, como la multiplicación entre el Número de Aventuras y la Habilidad Mágica en cuestión. De esa forma, a medida que aumenta la experiencia del personaje, aumenta la capacidad de canalizar energía mágica ({{{Regla de la Casa}}}).
Los jugadores deben escoger una [[Raza|Razas]] para su héroe.
Un jugador puede bajar voluntariamente el valor de alguna de sus [[Habilidades]] para cumplir los requerimientos de la raza elegida. Si desea aumentar algún valor, debe bajar un código de "A" o "B", en una relación de uno a uno.
De igual forma, puede bajarse voluntariamente el código de las [[habilidades]] para cumplir con algún requerimiento.
Bajo ningún concepto puede subirse un código.
A medida que un jugador se familiariza con el juego, puede desear que su héroe realice acciones más complejas:
*[[Apuntar]]
*[[Atajar]]
*[[Cubrirse]]
*[[Desarmar]]
*[[Distracción]]
*[[Escapar]]
''Por documentar:''
Agarre del Arma Enemiga
Agarre o Sometimiento
Interceptar
Maniobrar para Cerrar Rango
Cada persona que juega el rol de un [[Héroe]] puede hacer que su personaje intente acciones, declarándolas al Narrador. Si la situación es apremiante o tensa, aún las acciones más sencillas podrían fallar, por lo que se introduce cierto factor azar, mediante el uso de [[cartas|Cartas del Destino]].
Cada Jugador posee tantas cartas como indique el [[Tamaño de Mano]] en la hoja de personaje. Mientras un personaje es más experimentado, tiene mayor [[mano|Tamaño de Mano]]. El Narrador no necesita cartas para las acciones de los demás personajes de la historia.
Cuando un jugador escoge una carta de entre las que se encuentra en su Mano, de alguna forma está representando el esfuerzo o empeño que pone el personaje en lograr la acción. Si escoge una carta de bajo valor, está estimando que la acción es fácil, y si escoge una de alto valor está tratando de asegurar que la logra.
Hay dos tipos de acciones:
''Acciones No-Resistidas'': una acción No-Resistida o No-Opuesta se produce cuando la acción de un [[Héroe]] no es resistida por otro personaje o héroe. El éxito depende sólo de su propia habilidad, conocimmiento y talento.
''Acciones Resistidas'': una acción Resistida o con Oposición, se produce cuando el [[Héroe]] debe superar la habilidad, conocimiento y talento de otro personaje o [[Héroe]].
[[Ejecutando Acciones]]
[[Sistema Opcional de Pericias]]
[[Tareas de un Héroe]]
|bgcolor(#a0ffa0):''Acciones Estratégicas''|>|>|>|>|>|>|
|!Acción|!Dificultad|!Habilidad|!Habilidad Opuesta|!Comentarios|!Efectos|!Desgracia|
|Cambiar rango|8|Percepción|Percepción|Antes del combate|aumenta o disminuye el rango en una categoría|a juicio del narrador|
|Mantener rango|8|Percepción|Percepción|Antes del combate|evita que el oponente haga un cambio de rango|a juicio del narrador|
|Evitar sorpresa|8|Percepción|Agilidad|-|Fallo permite a los oponentes un contraataque gratis|a juicio del narrador|
|Sorprender|8|Percepción|Agilidad|-|Éxito permite a los héroes un ataque gratis|a juicio del narrador|
|bgcolor(#a0ffa0):''Acciones Ofensivas''|>|>|>|>|>|>|
|!Acción|!Dificultad|!Habilidad|!Habilidad Opuesta|!Comentarios|!Efectos|!Desgracia|
|Cargar|4|Agilidad|Agilidad|El héroe debe moverse en un espacio abierto, ganando momentum para golpear. Implica finalizar una acción de cerrar rango anteriormente. Es sólo contra un enemigo. El líder puede realizar una maniobra en la que todo el grupo hace la carga, en cuyo caso la dificultad aumenta a 8|Éxito otorga +3 a un ataque basdo en Fuerza, y -3 a la defensa del contraataque|El enemigo gana un ataque gratis|
|Cortar o Quebrar|8|Fuerza o Destreza|Resistencia o Agilidad|Si el objeto no es sostenido por nadie, la acción no es resistida. Se asume que el objeto no es particularmente fragil ni especialmente resistente. Ejemplos: cuerdas, frascos de metal, antorchas, sillas. Objetos pequeños o más resistentes hacen la acción más difícil. Los más grandes o débiles, la faciltan. En algunos casos el narrador puede asignar al objeto un puntaje de "Resistencia" haciendo necesario que el héroe haga "puntos de daño" al objeto para destruírlo. Se asume que el arma es del tipo adecuado. Ejemplo: No se usa una espada para romper una gema, ni un martillo para romper una cuerda.|El objeto es destruído, con Fuerza si es un arma cuerpo-a-cuerpo, o Destreza, si es un arma de misil.|El héroe se debe defender del próximo contraataque de forma inmediata. Si el objeto estaba "sólo", debe defenderse de si mismo por un ataque provocado por un giro inesperado o rebote.|
|Desarmar|12|Fuerza o Destreza|Resistencia|Normalmente no se inflinge dañ, pero si el puntaje de la acción excede al menos en 5 puntos la dificultad, el oponente sufre daño normal, además de soltar el arma. Puede combinarse con una "carga" o "ataque temerario" o "ambos"|El héroe hace que su enemigo suelte su arma (o algún item que sujete con la mano).|El héroe debe defenderse de un ataque gratis del oponente|
|Ataque rápido|-|-|-|No se puede mezclar con "carga", "gran golpe" ni "ataque temerario", ni se puede usar como ataque gratis ganado por una "desgracia" o "sorpresa".|Queriendo dar un ataque extra rápidamente, el héroe debe dejar abierta su defensa a contraataques. El ataque se resuelve de forma normal, justo luego de otro ataque (o, si se usa iniciativa, antes que actúe su oponente). No se podrá defender de un ataque del oponente (si éste continuara vivo luego del ataque rápido). Sin embargo, en el contraataque aplicarán las defensas de armadura y escudos.|El héroe es atacado inmediatamente, y el golpe se recibe de forma automática.|
|Arrebatar|8|Fuerza|Fuerza|Puede hacerse en el mismo minuto en que se cierra el rango o se hace un agarre, pero esto lo hace más difícil. No se puede hacer con items muy pequeños o peligrosos como anillos o dagas, a menos que se haga un "agarre" antes.|El héroe que cierra el rango a "personal" puede arrancar algo que tenga o sostenga su oponente. |El héroe recibe un ataque gratis|
|Agarre/sometimiento|12|Fuerza|Fuerza|El héroe no puede intentar otra acción (salvo por un arrebate de algún objeto), mientras mantenga el agarre. Puede hacer el agarre en el mismo minuto en que cierra el rango a "personal".|El héroe inmobiliza al enemigo usando ambas manos. Hace daño igual que cualquier otro ataque desarmado basado en Fuerza. Evita que el oponente ataque. En el siguiente turno, mantener el agarre e inflingir daño es una acción fácil (4) de Fuerza contra Fuerza. Si falla, el héroe tiene una penalización de -3 en la próxima defensa.|Recibe un ataque gratis|
|Gran Golpe|-|Fuerza|Resistencia|Puede combinarse con una "Carga" añadiendo +3 a la acción de Fuerza del ataque, antes de duplicarse (el oponente tendrá un bono de +3 contraatacando luego). No puede usarse en un ataque gratuito producto de una "desgracia" o "sorpresa".|Se da un golpe extra-desvastador, quedando el héroe vulnerable a contraataques. Se duplica la Fuerza al calcular el ataque, y posteriormente está imposibilitado para defenderse.|Recibe un ataque del oponente, sin poder poner resistenca|
|Ataque Temerario|-|-|-|Cuando se combina con una "carga", se puede aplicar el +3 a la carga de ambos ataques. Un ataque temerario no puede ser utilizado para un ataque gratuito.|Es una acción extraordinariamente ofensiva que deja al héroe en vulnerabilidad. Es un segundo ataque luego del normal. Impide realizar oposición a los contraataques del siguiente turno.|Ataque gratuito del oponente, sin posibilidad de defensa.|
|Colarse|8|Agilidad|Agilidad|Si nadie está envuelto en combate a rango personal, el lider puede intentar arremeter por todo el grupo. No se puede atacar cuando se arremete, sin ocasionar un contra-ataque contra el cuál no se puede oponer resistencia, salvo por los valores de armadura y escudos. Puede combinarse con un Golpe de Escudo o con un ataque normal, pero debe tratarse la acción combinada como si fuese un Ataque Temerario. Un grupo de héroes que desean pasar a través de los enemigos, deben derrotarlos en combate, o cerrar el rango a cuerpo-a-cuerpo e intentar arremeter contra el enemigo. Posteriormente, debe realizarse una acción de abrir rango, para escapar.|Permite al héroe que está a rango cuerpo-a-cuerpo o personal, pasar a través de la línea de sus oponentes.|Ataque gratis del enemigo contra el grupo o el héroe que intentó colarse. Si se intentaba el colarse mientras se atacaba, el enemigo tenrá dos ataques. Los héroes no podrán utilizar ni Endurance ni Agility|
|Golpe de Escudo|8|Fuerza|Resistencia|Para determinar el éxito de la acción el rating del escudo se suma a la acción de ataque del héroe.|Se usa [[El escudo como arma]] cuerpo-a-cuerpo.|
|Derribar|12|Fuerza|Fuerza|Puede realizarse en el mismo minuto en que se cerró rango a "personal". Si falla, el oponente gana +3 a Fuerza para su próximo ataque, como si el héroe estuviera realizando una Carga. Puede realizarse cualquier acción posible a rango personal, y tiene un +3 a la acción. Si luego del derribamiento, se realiza un agarre, el oponente no puede ponerse de pie hasta tanto no se libere.El héroe no puede cambiar el rango ni colarse a través del oponente. Cuando el héroe deje de estar sobre el oponente, éste debe perder su turno en ponerse de pie. Intentar que el oponente no se ponga de pie, es un Agarre. El oponente puede contra-atacar en lugar de ponerse de pie, a rango personal|El héroe tumba a su oponente al suelo. Queda sobre el enemigo, quién es incapaz de contraatacar. No hace daño, pero deja al héroe actuar de primero automáticamente en el próximo minuto de combate.|El héroe cae, en lugar del oponente, otorgándole un ataque gratis con un bono de +3 a la Fuerza. También puede derribar de gratis al héroe.|
http://rpggeek.com/thread/674899/how-to-fix-the-saga-system-for-5th-age
Kender Nightstalker
Ability Scores Ability Codes
AG 7 min AG D max
DX 7 min EN D max (true) or C max (afflicted)
EN 6 max SP B
ST 6 max PE B min
SP 4 min
PE 6 min or PR 6 min
Other Requirements: Kender only; acute eyesight; sensitivity or spiritualism required; other requirements by subrace.
Advantages
SP or PE action to detect spirits; spirits attack only on a black aura draw; handling; trump bonus for sleight-of-hand (true) or sneaky (afflicted) actions; can adopt role during play.
Disadvantages
Meets oppositions from other heroes; short concentration; A code allowed only for PE.
The Acrobat Role
By Eric Jwo
Acrobats are rogue heroes who have mastered their tumbling and acrobatic skills in order to accomplish their goals. Many acrobats use their skills to perform in
traveling shows or to entertain the wealthy. Acrobat-thieves use their skills to walk along tightropes to reach their marks, climb sheer walls, and avoid law
enforcement. Acrobat-warriors often use their skills to dodge enemy weapons, overcome physical obstacles, and to evade their enemies.
Acrobats have spent years perfecting their skills. They have trained for so long that tumbling, dodging, catching, and climbing are second nature to them. Whereas a
warrior might back into a table to avoid a quick sword thrust, an acrobat would somersault backwards over the table automatically.
Acrobats have their own fighting styles as well. Jackie Chan movies provide a great example of an acrobat's fighting techniques, since his mixture of dodging and
improvising exemplifies the acrobat's skills.
An example of an acrobat is Calarran from the short story "Lessons of the Land." Gem from "The Magnificant Two" is also a good example of an acrobat. Both of
these short stories appear in the Dragonlance anthology entitled Dragons of Chaos.
Requirements
An acrobat depends greatly on his Agility and Dexterity to perform his skillful feats. Therefore, an acrobat needs a minimum score of 7 in both Agility and Dexterity.
However, this strenuous training depends on an acrobat to be lithe and slim. An acrobat cannot be large and muscled and still perform adequately. Therefore, an
acrobat has a maximum Endurance score of 5. Acrobats tend to remain aloof. Acrobats are talented at sneaking and dodging, but not leading. Therefore, an acrobat
has a maximum Presence score of 5.
Acrobats spend a lot of time improving their Perception and Dexterity. Therefore, an acrobat must have a code of "B" or higher in both Dexterity and Perception.
The time spent on their training limits an acrobat's knowledge of the arcane. Therefore, an acorbat has a maximum score of "B" in Spirit, and a maximum score of
"C" in Reason. The strenuous training of an acrobat also limits an acrobat's knowledge of the art of war. Therefore, an acrobat has a maximum code of "B" in
Strength.
Only human, elves, half-elves, and kender may adopt this role. This role cannot be adopted during play.
Advantages
Acrobats are superbly trained and have taken advantage of their skills. Any Agility action, such as dodging an arrow, walking a tightrope, completeing a somersault,
or dodging a boulder, is automatically considered a trump. Dexterity actions involving thrown weapons, improvised weapons, and acrobatic feats are also
considered trump bonuses.
Disadvantages
An acrobat needs to remain light and unemcumbered in order to utilize his skills. Therefore, an acrobat cannot wear armor heavier than leather. Also, an acrobat
needs to keep his hands free and ready. Therefore, an acrobat cannot wear gloves or gauntlets, cannot use shields, and an acrobat cannot use two-handed weapons.
While teh above weapons may be used temporarily (such as picking up a shield to block an arrow, grabbing a staff to fend off a foe, etc.), they cannot be carried
around by an acrobat as permanent possessions.
Also, acrobats are particularly susceptible to magic. Acrobats never receive a trump bonus to resisting sorcery or mysticism. Should an acrobat hero ever learn a
sphere of mysticism, this sphere must be the sphere of channeling.
If you have any comments on my page, or want to submit stories, ideas, etc., then e-mail me at Eric94087@aol.com.
Puede saberse más de este sistema en [[esta página|http://en.wikipedia.org/wiki/Editions_of_Dungeons_%26_Dragons#Advanced_Dungeons_.26_Dragons]]
Debo agradecer primeramente a [[Tracy Hickman|http://www.trhickman.com/]] y [[Margaret Weiss|http://www.margaretweis.com/]] por haber creado este mundo o //setting// tan especial.
En segundo lugar, debo agradecer a mi hermano Rodex. Gracias a él llegó a mi este universo que llamamos Dragonlance. ¡Gracias hermano! Nunca olvidaré ese viaje en autobus en el que te dedicaste a contarme todo el libro 1 de Crónicas. Subí al bus sabiendo nada, y bajé de él con los héroes de la lanza en el corazón, y unas ganas irrefrenables de leer Crónicas, Leyendas y El Ocaso de los Dragones.
En tercera instancia a todos los autores que han colaborado a expandir cada vez más el mundo de la DragonLance, y por qué no, a quienes dirigieron esto y lo hicieron posible: TSR y Wizards of the Coast.
Y no debo finalizar mis agradecimientos sin mencionar a todos aquellos que han aportado para mantener vivo este universo fantástico, sin recibir nada a cambio: Los Fans.
Muy especialmente a la gente de [[DragonLance Nexus|http://www.dlnexus.com]], a los artistas que han poblado este site con su //fan-art//:
*atongwali
*[[Brett Wiseman|www.brettwiseman.com]]
*Canlocu
*Cell
*Chris Untch
*David Davidson
*Eriane Blais
*Hugh Vogt
*Icegal
*Irina Vargas
*Jennifer Meyer
*Ksar
*Lindsay Archer
*Nick Barfuss
*[[PsychaDurmont|http://www.dlnexus.com/contributors/1879.aspx]]
*Sandara3
*Thor [the powerhead]
*William Teo
[img[http://www.dlnexus.com/gfx/site/nexus.gif][http://www.dlnexus.com]]
He utilizado también trabajos de Mandrak por su trabajo en Worth1000.com y [[JeiWo|http://jeiwo.deviantart.com/]] y [[ArchTempest|http://archtempest.deviantart.com/]] por el suyo en ~DeviantArt.com
También, por último, quiero agradecer a los fans que han realizado artículos para jugar en condiciones diferentes a las que se muestran en el material oficial, como por ejemplo:
[[James Lai|mailto:synicism1@worldnet.att.net]]
[img[Arte por Nick Barfuss en www.dlnexus.com|http://www.dlnexus.com/gfx/art/19657.jpg]]
[>img[Imágen de http://4.bp.blogspot.com, pero de autor desconocido. Si usted conoce el autor, por favor indíquemelo para contactarle y pedir el permiso oficialmente para mostrar el dibujo, y hacer el reconocimiento como es debido|http://4.bp.blogspot.com/_hqS11yCxnQ8/TEN4nBGiVmI/AAAAAAAANdQ/F5RPikR_Gyc/s1600/barbarian.jpg]]
Amazons are rare on Ansalon, but make their presence known. Amazons are tribes of human warrior women that have a deep hatred for males of almost every race (kender & gnomes are usually an exception, and their hatred extends towards centaurs as well) for their dominance over women, and go to great lengths to exterminate this subjugation and sex. Males caught venturing into Amazon territory are usually killed, if not, they are put to some mundane use (sacrifice, torture...). You can almost always tell if a tribe of Amazons live nearby, for the village will have a complete lack of females. Amazons raid surrounding villages about once a year, not to pillage, but to abduct small girls and have intercourse with the males. When the children are born, boys are left in cradles on river shores or the like.
Role Playing: A lone Amazon is rare, but one adventuring alone away from the tribe is even more so. Amazons don't hide from what they stand up for; they gladly flaunt it. To an Amazon, all males are the same: overbearing, wife-beating, piggish sloths that are around only to create more females. An Amazon will stand up and for her beliefs, no matter what the cost.
Requirements: First off, and obviousely, the character must be female. Amazons are extremely fit, and never overweight, due to intense combat training. Therefore, all Amazons must have at least a 5 in Strength with a code of B, a 6 in Dexterity, with a code of at least C, a 7 in Endurance and Agility, and Presence must be at least 5, due to their outspokeness and strong beliefs. Amazons never train in heavy armour, therefore their Endurance code can never be higher than C. Spellcasting Amazons (rare) must have a 5 in Spirit or Reason (or both), but can ignore the Strength requirement.
Advantages: Amazons have a deep hatred of men, and when they first attack a man, they revieve a trump bonus. This applies only to the first man attacked in the combat; an attack subsequent men won't recieve this bonus. (Man is defined as being human, dwarf, or elf... the more intelligent and civilized of the humanoid races.) Due to their intense training in warefare, Amazons recieve a +1 to attack and damage of a weapon of their choice, and a -2 to defence, from strenuous and daily training in acrobatics and tumbling.
Disadvantages: Amazons hate men, and rarely associate with them, other than for intercourse or war. If they do associate with men, they never recieve a trump bonus when dealing with them.
Of all the types of Kender, his fellows admire one above all. The Kender themselves don't really have a name for such an individual, except perhaps "role modle" or "hero". The rest of Ansalon, however call him a handler.
More so than any others of his race, this hero always seems to know when to seek adventure, where to find neat stuff and how to extract himself from trouble. He is truly a kender's kender.
Most even-tempered individuals know kender don't steal purposely-they just forget what is and isn't theirs. As with all kender, curiosity and an insatiable hunger for new experiences motivate handlers to action. They prove more capable than most kender at satisfying their curiosity, however: It is a rare lock or magical ward that a handler can't get around. Once he sets his heart on obtaining an object, he invariably will get his hands on it-unless something more interesting comes along, of course.
!Role-playing:
While kender handlers live to purloin, they do not purloin to live. Unlike thieves and bandits, handlers do not act out of greed, but out of curiosity. The more forbidden and protected an item is, the more curious the handler becomes.
Once he has obtained and examined it, however, he often loses interest. Thereafter, he may absent-mindedly lose the item or pass it along to friends with an interest in such things. (This is why the Legion of Steel makes a con-certed effort to befriend kender: One never knows when a handler might tire of a set of secret battle plans he has secured from a Knight of Takhisis.) A handler has absolutely no interest in the financial value of an item. An ornate brass-plated clay statue will hold his attention far longer than a priceless but boring raw diamond.
Tasslehoff Burrfoot was a notorious handler. (Just ask anyone who ever met this legend what he lost!)
!Requirements:
Although not all kender are handlers, all handlers are kender. As only true or afflicted kender may adopt this role, they must meet the basic requirements for that race, as outlined in Chapter One of the Book of the Fifth Age. Addi-tionally, in order to be a handler, a hero must have a score of 8 or better in both Agility and Dexterity.
!Advantages:
Regardless of his actual background, the hero is considered nobility (wealth 8) when interacting with kender who know him-they try to please him in pretty much any way they can. He also enjoys a trump bonus for Presence actions directed at such kender.
Whenever the handler meets a new group of kender, his player turns over a card from the Fate Deck to see whether they recognize him. (Any kender who recognize him treat him as detailed above.) Drawing a card with a white aura means the new kender know him by sight. A red aura indicates that they recognize his name, while a black aura suggests that they are unfamiliar with him. Of course, handlers who don't want to be recognized can disguise themselves with average Reason (Per-ception) actions. They can also attempt average Presence (Perception) actions to deny that they are who the new kender think they are.
Handlers also receive the advantages listed for their race in Chapter One of the Book of the Fifth Age.
!Disadvantages:
While handlers are treated like heroes among their own kind, most other folk are less than thrilled with them. Once a community of nonkender has identified a handler as such, he no longer enjoys a trump bonus for Pres-ence actions and he suffers a -2 penalty to all his action scores there. Furthermore, innkeepers and mer-chants will keep an extra close eye on the handler and overcharge him to make up for any items he has "han-dled" while in their establishment. Regardless of the handler's back-ground, his effective social status falls to that of a peasant (wealth 2).
To see whether others recognize a handler for what he is, the player turns over a card from the Fate Deck Drawing a Dragons card means someone in the community has either witnessed him "handling" or has, by a strange coinci-dence, encountered the hero elsewhere.
In most cases, recognition proves merely inconvenient for the kender and his friend, for instance, the local law follows them around during their visit. However, if the heroes find themselves in a town harboring a group of covert Knights of Takhisis, a clandestine circle of Solamnic Knights, or (worst of all) a gang of cutthroats about to conduct a major heist, the heroes may find them-selves in grave danger: All three of these groups would rather not risk a handler, renowned for his ability to get at things hidden, getting wind of their activities.
Handlers also receive the kender racial disadvantages. Heroes can't adept this role during play-handlers is born, not bred.
El héroe gasta un turno en apuntar, haciendo que la dificultad baje en un nivel (4 puntos). No puede hacer ninguna otra cosa (ni siquiera defenderse) mientras apunta. Si cambia su acción o recibe daño mientras apunta, pierde la bonificación.
Las armas de las tribus bárbaras son las siguientes:
|!Terreno|!Armas|
|Desierto|Colmillo "kala" de la muerte, garrote, arco de jinete, lanza ligera, cimitarra, hojillas voladoras, faja con pesos|
|Bosque|Hacha de batalla, Hacha de mano, cuchillo, arco largo, //mallet//, vara, honda, mazo de guerra.|
|Hielo|Cudgel, frostreaver, ballesta de hielo, frasco de hielo, granada de hielo, lanza, piedras lanzables|
|Llanuras|//Bolas//, arco de jinete, lazo, lanza ligera, cadena dentada, throwing stick, mazo de batalla|
|Montañas|Cualquier hacha, garras de oso, cualquier arco, hoja cook, arco pellet, jabalina, pipa de guerra|
|Mar|Belaying pin, colmillo , hookshaft sabre, tridente, arpón.
Weapon Type Class DMG Description
Sword: Stiletto Melee* VL +1 6 inch needlelike blade
Dagger Melee* VL +2 8 inch blade
Short Sword Melee L +3 15 inch blade
Cutlass Melee L +4 30 inch curved blade
Scimitar Melee M +5 3 foot curved blade
Sabre Melee M +5 See Heroes of Steel
Broad Sword Melee H +6 3 foot blade
Crook Blades Melee H +6 See Heroes of Steel
Long Sword Melee H +7 3.5 foot blade
Two handed Melee VH +8 4 foot blade
Great Melee VH +9 5 foot blade
Hammers: Sap Melee VL +1 Leather pouch of lead pellets
Belaying Pin Melee VL +1 Short wooden peg used for ship rigging
Mallet Melee* VL +2 Small, Short handled, and metal hammer
Baton Melee VL +2 Slender wooden club
Bludgeon Melee L +3 Short weighted club
Cudgel Melee L +4 A traditional club
War Club Melee M +4 See Heroes of Steel
Mitre Melee M +5 A short sturdy mace
Flail Melee H +6 Two batons connected by a chain
Mace Melee H +7 A haft with a heavy head
Morning Star Melee VH +8 A heavy spiked mace
War Hammer Melee VH +9 A hammer with large spike
Tessto Melee VH +9 See Heroes of Steel
Axes: Adze Melee VL +1 A carpenters tool
Hand Axe Melee* VL +2 A carpenters tool
Sickle Melee L +3 A slender crescent blade
Scythe Melee L +4 Sickle mounted on a staff
Gnome pick Melee M +5 See Heroes of Steel
Pick Melee M +5 A heavy spike-like mining tool
Battle Axe Melee H +6 A hefty axe with a spiked head
Broad Axe Melee H +7 A single bladed headsman’s axe
Great Axe Melee VH +8 Double bladed broad axe
Frostreaver Melee VH +8 See Heroes of Steel
Poleax Melee VH +9 Broad axe on a shaft
Polearms: Quarterstaff Melee VL +2 6 foot iron shod pole
Javelin Melee* VL +1 Slender spear for throwing
Spear Melee* L +3 Traditional throwing weapon
Fork Melee* L +4 Long shaft with 2 spikes
Trident Melee* M +5 3 Prong spear
Lance Melee H +6 A heavy spear (incl. DragonLances)
Billhook Melee H +7 A staff with many pronged tip
Pike Melee VH +8 A staff with a spiked tip
Halberd Melee VH +9 A staff with a spike-bladed tip
Bows: Prodd Missile VL +1 Pellet firing crossbow
Self Bow Missile VL +2 Simple Bow
Pellet Bow Missile L +2 See Heroes of Steel
Light Crossbow Missile L +3 Basic Crossbow
Horsebow Missile L +4 Built and backed recurved bow
Ice Crossbow Missile M +4 See Heroes of Steel
Crossbow Missile M +5 A stirrup drawn bow
Longbow Missile H +6 Large recurved bow
Heavy Crossbow Missile H +7 A crank drawn crossbow
Greatbow Missile VH +8 Large compound recurved bow
Arbalest Missile VH +9 A massive crossbow
Singing Bow Missile VH +9 See Heroes of Steel
Unusual: Lasso Melee VL +0 See Heroes of Steel
Whip Melee VL +1 A simple whip
Bear Claws Melee VL +1 A pair of leather gauntlets with iron spikes
Blowgun Missile VL +1 A long hollow tube for firing darts
Shuriken Melee* VL +1 An oriental Throwing star
Garrote Melee VL +1 Thin length of cord/wire
Ice Flask Missile VL +1 See Heroes of Steel
War Dart Melee* VL +2 A heavy barbed dart
Death’s tooth Melee VL +2 resembles a dagger
Sling Missile L +2 A strap for hurling stones
War Pipe Melee* VL +2 Used by mountain Barbarians
Weighted Sash Melee VL +2 A silk sash with metal weights
Whippik Melee VL +2 A kender weapon
Bolas Melee* L +2 A desert weapon
Fang Melee L +2 See Heroes of Steel
Ice Grenade Missile L +2 See Heroes of Steel
Throwing Stick Melee L +2 See Heroes of Steel
Throwing Stone Missile L +2 See Heroes of Steel
Throwing Blades Missile L +3 See Heroes of Steel
Caff Melee L +3 See Heroes of Steel
Soris Melee L +3 See Heroes of Steel
Teeth chain Melee L +3 See Heroes of Steel
Oil Flask Missile L +3 See Heroes of Steel
Hookshaft Melee M +4 See Heroes of Steel
Staffsling Melee* M +4 A sling on a long pole
Hoopak Melee* M +4 Same as Staffsling but shorter (for Kender)
Chakrum Melee* M +3 A sharp edged throwing disc
Armour: Padded Silk N/A VL -1 Quilted suit of silk & cotton (mage robes)
Leather N/A L -2 A Suit of stiffened and boiled leather
Chainmail N/A M -3 A suit of fine metal Mesh
Elven Chain N/A L -4 Better than ordinary chain
Scale N/A H -4 Suit of small overlapping plates
Dragonscale N/A H -5 Same as scale fut made with dragonscales
Plate N/A VH -5 Traditional Knights Armour
Shields: Buckler N/A VL -1 Very small circular Shield
Bracers N/A L -1 Arm Bracelets (hand-forearm)
Kite N/A L -2 Small triangular Shield
Target N/A M -3 A heavy circular Shield
Horse N/A H -4 A heavy triangular Shield
Tower N/A VH -5 A massive rectangular shield
* Also can be thrown
[[El escudo como arma]]
Los arqueros prefieren el combate con armas de misil, sobre cualquier otra forma de combate.
Este rol incluye a los franco-tiradores de las diferentes milicias de Ansalon, a los que se dedican a exponer sus proesas en ferias, y a cualquier otro tipo de especialista en el ataque a distancia.
!Personalidad
Tienden a ser héroes cautelosos por naturaleza. Un tiro difícil de arco requiere el análisis paciente de los movimientos del objetio. Esto puede ser una característica del héroe ante cualquier decisión importante.
!Requerimientos
Casi todos los arqueros han dedicado gran parte de su tiempo a desarrollar manos precisas y agudeza visual, lo que debe verse reflejado en un valor de al menos 5 tanto en Destreza como en Percepción. El uso intensivo de las armas de misil implica que deben tener un código de A en Destreza.
Debido a que los escudos no ayudan en el uso de armas de misil, la mayoría no los usa, o en todo caso usa uno del tipo "buckler". El código de Agilidad debe reflejar ésto, con un código igual a C o menos.
En general, dedican tanto tiempo a la práctica de armas de misil, que no emplean mucho tiempo para entender la magia, lo cuál se debe reflejar en un código máximo de "C tanto para Espíritu como para Razonamiento.
Sólo centauros, humanos, elfos y medio-elfos pueden adquirir éste rol.
!Ventajas
Un arquero debe escoger un tipo e misil como su especialidad (gran arco, ballesta, daga lanzable, etc.). Cualquier carta jugada con ese tipo de arma, automáticamente recibe el bono de una [[Carta de Triunfo]].
!Desventajas
Un arquero sufre -3 a todas las acciones de fuerza mientras realice ataques a rango personal o de cuerpo-a-cuerpo.
Street Performer
Ability Scores Ability Codes Other Req.’s Advantages Disadvantages
Ag 4 min. Ag “C” min. Wealth 3 max. Can Play/dance No trump bonus to Pr
Pr 4 min. Pr “C” min. automatically or with a actions to deal with middle
Sp “C” min. trump bonus; easy Pr or upper classes.
action to learn information;
heroes with musical skill
can acquire role during play.
There are those among the peoples of Krynn who live outside the laws of society, those who believe emotion is a weakness of lesser mortals. They live only for the individual, for themselves, and for the pleasure of murder. These beings have no interest in anything besides money(with few exceptions),
and are not above selling their services to the highest bidder. They dwell in the darkness, revel in the kill, and hold all others in contempt. They are assassins.
Unlike thieves, there are no assassins' guilds upon Ansalon. These rebels prefer to work in secret, unbeknownst to anyone besides their employers. Few assassins openly flaunt their occupations, for doing so is virtually suicide. Indeed, the unfortunate victim rarely knows he is targeted until the last, fearful seconds of his life.
Most assassins consider murder an art, using many intricate factors to guarantee success. They are skilled in wielding small, subtle weapons such as knives and daggers, able to injure a victim most painfully when necessary, to the point of torture.
Glome the Assassin from The Covenant of the Forge and Slickblade from The Last Thane are both excellent examples of assassins.
!Role-playing:
To "normal" individuals of all races, assassins appear to be cold and heartless killers, their only love that of killing and money. In most cases, this isn't far from the truth. Assassins only speak when they believe it will prove to their advantage, and feel no need to help those who won't pay for the assistance, even their own allies or families. This is because, at one point in their lives, these people learned that mercy is weakness, that compassion holds only death, and that trust is without substance.
A few select races grudgingly accept the assassin as a useful ally. Among these are the Theiwar, Daergar, and Klar mountain dwarves, the humans of Sanction, Neraka, Ackal Province, Estwilde, and Khur, the minotaur priests, and most goblins and ogres. Naturally, the Dragon Overlords, especially Malys, value assassins as some of their most skilled pawns.
!Requirements:
For a hero to qualify as an assassin, he must have Agility and Dexterity scores of at least 6, and Reason and Perception scores of at least 5. No hero with a Presence score above 6 may be an assassin.
As assassins excel in lightweight weapons and armor, these heroes must have a ability code of "C" or less in all physical abilities. Because they operate by themselves, no assassin may have a Presence code above "B". Also, impaired assassins tend not to live very long, so they must have Perception codes of "C" or higher.
Due to the fact that these killers must be merciless and cruel to remain sane, no assassin may have a nature score of 4 or less.
!Advantages:
As these dwellers of the night rely on ambush to vanquish their enemies, assassins enjoy a trump bonus for all actions that involve gaining and avoiding surprise.
An assassin's skill in small, lightweight weapons is unparalleled. Any card an assassin plays when attacking with one of the following weapons is considered trump: Dagger, death's tooth kala, light crossbow, shuriken, sickle, stiletto, throwing blades, war dart. A hero may have three such favored weapons.
Heroes with the proper background may become assassins during play.
!Disadvantages:
Because these heroes have such heartless natures, no Presence action performed by an assassin is considered trump. Also, when attempting Presence actions involving heroes or characters with nature scores of 4 or less, assassins also face a -2 action penalty.
Since an assassin is very likely to gain quite a few enemies in his scandalous missions, he must constantly change his alias. More than a few of these disgruntled foes are the loyal servants of a late victim of the hero, and once per quest he will have to draw a card from the Fate Deck to see whether he will face an agent or agents of his enemies. Should he draw a card with a white aura, he encounters no enemies this quest; if he draws a red aura, he discovers evidence that his foes will face him during his next quest; if he draws a black aura, he will be confront by his adversaries sometime during the current quest.
Some of his stalkers may be assassins themselves, or a minion of a former employer who believes this hero's usefulness has ended. These encounters do not necessarily have to be combat scenes—it might not even be a life-and-death situation—but it should feel tense and threatening.
It should be noted that if the hero changes roles during a campaign, his foes will continue to stalk him as described
The Citadel Aspirant
At the Citadel one can find mystics of all levels of training, from novices to masters. The role of the Citadel Aspirant describes the novices, heroes of great spiritual promise who have yet to fulfill their potential.
While it may seem odd to play a mystic with no mystical spellcasting powers, this is the perfect kind of hero for A light in the Darkness, the adventure in Book Two. In fact, many of the heroes described in its Prologue hope to become Citadel Aspirants.
Role-Playing:
Aspirants tend to come in two varieties, Some are wide-eyed youths or other idealists eager to make a difference in the world. Just as many are jaded former street urchins, warriors, and others who have seen too much tragedy in their lives; they feel that if they don´t master the powers within them, the world will continue its downsward spiral toward inevitable self-destruction, for only they have the power to stop it.
The two kinds of mystics-in-the-training don´t always get along well. Generally speaking, though, the exuberant, optimistic students learn restraint and patience from the world-worn ones, while the reminder of innocence they provide tempers some of the others´ cynism. Since the screening process ensures that all students of the Citadel are basically kind-hearted, small personality conflicts rarely scalate into feuds or full-fledged hatreds that would disrupt the aspirants´ learning and growth.
Requirements:
Aspirants are men and women with great spiritual potential who have not yet mastered the powers that dwell within them. They must have Spirit scores of 4 or better, but their Spirit codes cannot be higher than a “C”. Heroes with this role gain their spell-casting powers over several quests.
Under rare circumstances, heroes with “B” or “A” codes can be considered aspirants. These heroes are trying to improve their Spiritual scores rather than their codes. They have discovered their mystical talents on their own, but are not strong enough in Spirit to wield any discernible force. For example, a hero who adopted the medium role but has a Spirit score of 2 points might choose to enter the Citadel of Light for training. Instead of increasing in code, this hero would work of improving the ability score.
Once heroes can cast spells outside the magically enhaced training halls –and when thier Spirit ratings are at least 4B, their reputation at least Adventurer, and they have climbed the Silver Stair as described in A light in the darkness- the heroes automatically adopt the role of Citadel mystic. From there they can move on to other Citadel-related roles.
If an aspirant enters into mystic training as a skilled warrior, the hero´s Physical codes generally deteriorate while he or she concentrates on more mental pursuits. Therefore, by the time the aspirant is ready to move on to the role of Citadel mystic, he or she has Strength and Dexterity codes of “C” or lower and Agility and Endurance codes of “B” or lower to meet that role´s requirements.
Note: if a channeler, Knight of Solamnia, etc. Wishes to retain skills at arms, perhaps the hero´s original role or that of the “mystic-warrior” (from Heroes of Hope) would be more appropriate, as it would not require a decrease in Physical codes. However, the hero´s Citadel studies will take longer than normal if he or she spends time in weapons practice.
Advantages:
Many heroes with this role have an easier time raising their ability codes than other heroes, because they arrive at the Citadel of Light virtually unware of the powers within them. Thus they remain free of preconceptions that might make them less than receptive to the teaching methods developed by Goldmoon.
Aspirants improve in Spirit code through role-playing these tests rather than using the method described at the end of Chapter One in the Book of the Fifth Age. The rules for improvement through role-playing appear in the Prologue of Book Two, wich is for the Narrator´s eyes only; see also Act Two of A light in the Darkness. Hero aspirants who seek to elevate their Spirit Scores instead of their codes may do so through role-playing as well.
The role of aspirant can be adopted during play.
Disadvantages:
Aside from having to earn their spell abilities through play, mystics-in-training have no disadvantages. Naturally, such heroes will not gain acces to the sphere of necromancy, becauses no Citadel mystic will teach it.
Un héroe con un rol que implique entrenamiento en artes marciales o con una Destreza excepcional, puede intentar una acción de dificultad desalentadora (dificultad base 16) para atajar un misil lanzado hacia él.
En general, el aura de las cartas tiene significado particular, según se muestra en la siguiente tabla:
|!Aura|!Valor|!Significado|
|Blanca|1-3|Bondad y virtud, energías positivas|
|Roja|4-6|Respuestas neutrales, lo que es ni bueno ni malo, equilibrio|
|Negra|7-9|Corrupción y maldad, energías negativas,desconfianza (toda carta dragón tiene aura negra)|
En algunas ocasiones se puede usar el Aura para resolver una acción:
#''Método No aleatorio'': el narrador, una vez por sesión o escena (si resulta dramáticamente evidente que todos los jugadores tienen cartas de valor bajo), puede pedir chequear la acción basándose en auras. Si el aura es blanca habrá éxito, si es roja, el resultado será neutro, si el aura es negra, la acción será fallida. Esto permite a los jugadores deshacerse de las cartas de menor valor (1, 2, 3) pues son las que tienen aura blanca.
#''Método Aleatorio'': El narrador, ante acciones rodeadeas de misterio, desconocimiento, o que desafían cualquier interpretación numérica, puede solicitar este tipo de chequeo. Básicamente extrae una carta del mazo, y lee el aura de la carta. Por ejemplo, un héroe dispara flechas a la oscuridad de una cueva, sin estar realmente en la posibilidad de apuntar a algo. Una posibilidad pudiera ser solicitar un chequeo aleatorio de aura. También, por ejemplo, podría utilizarse para determinar si un personaje cae de pie, de lado o de cabeza, al caer por una trampa en el piso.
*[[¿Qué es SAGApedia?|SAGApedia]]
*[[¿Como navegar en SAGApedia?|Navegación en la SAGApedia]]
*[[¿Qué es TiddlyWiki?|TiddlyWiki]]
[>img[imagen de flickr.com de Howard (toticat2002) (hacer clic para ir a su página)|http://farm4.static.flickr.com/3261/2597478277_23af97780b_m.jpg][http://www.flickr.com/photos/howard-jordi/]]
!Requerimientos
*Valor Mínimo 6 en Resistencia (End) y Fuerza (Str)
*Valor Máximo de 7 en Razonamiento (Rea)
*Código de Resistencia (End) D máximo.
*Código de Fuerza (Str) y Percepción (Per) B mínimo.
*Código de Razonamiento (Rea) X mínimo.
!Otros Requerimientos
Vista aguda y según el rol escogido.
!Ventajas
*Se desplazan en el agua como si estuveran caminando. Categoría de defensa -2. [[Carta de Triunfo]] para resistir miedo y emociones.
!Desventajas
*Nunca podrá tener [[Carta de Triunfo]] para relacionarse con, o entender a las otrs razas.
Where learned men such as those in Astinus's order of Aesthetics in Palan-thas devote their lives to chronicling the major events of history in books, the bards of Ansalon wander from vil-lage to village collecting songs and local folktales. Historians concern them-selves with kings and truth, while bards pay more attention to the common man and ripping-good yarns.
Bards-an important but seldom-recognized part of society-rarely appears in big cities like Palanthas or Solanthus. They leave those stomping grounds to the younger street performers, and hence often go unnoticed by "authoritative" (and urban) historians.
Ansalon's bards come in many different stripes. In the desert land of Khur and the polar Icewall Glacier they often serve as tribal shamans as well as storytellers, lending a moral significance to most of their tales. Bards of Abanasinia and the Plains of Dust specialize in romances and love ballads. Many popu-lar songs of the last fifty years revolve around the War of the Lance, a time now viewed as an age of grand heroism.
In Solamnia, the Estwilde, and among minotaurs and goblins, the bards generally former street performers specialized in supposedly historical sagas filled with exaggerated accounts of heroic deeds. Kender and gnomish bards create tales and songs even more fantastic. Popular kender tunes include:
* "Toede of Flotsam," which chron-ides a trip to the Abyss and back, supposedly taken by the aging hob-goblin general-turned-poet-philosopher-ruler;
* "Go for the Toe," the tale of how Hero of the Lance Tasslehoff Burr-foot defeated the Chaos god by stab-bing him in the big toe; and
* "The Kender Cleric of Chemosli," a tale of a kender hero who bluffed his way in and out of Sanction at the height of the Dark Queen's power during the War of the Lance.
Bards in Ergoth and Saiffium study at bard colleges, where they learn something from the repertoire of all the other bardic types. The elf Quevalin Soth, mentioned in Chapter One of Dusk or Dawn, is one of Analson's best-known bards.
!Role-playing:
Bardic heroes can be varied as the songs they sing. The most famous bards can command hundreds of steel pieces for a single night's performance at a lord's party, while others wander the countryside, telling tales in exchange for food and a place to sleep. All of them, however, share a love for storytelling and an almost insatiable curiosity about legendary sites, fabled heroes, and current events.
Almost without fail, these heroes love to gossip even more than old maids. For this reason, small, isolated villages welcome them with open arms, viewing their tales as news~ven if they hold only a fraction of truth.
Generally speaking, these heroes have gregarious and outgoing personal-ities. No bard has ever been known to turn away an eager audience unless he had pressing business elsewhere. Even the richest, best-paid bards give spon-taneous performances to children on street corners or entertain a village of poor peasants for free. A bard's life is all about the telling of the tale, and the wonderment, sorrow, or amusement that goes hand-in-hand with it.
Note: As bards travel from place to place, groups like the Legion of Steel often recruit them to carry messages from cell to cell.
!Requirements:
To sing their songs and tell their tales with passion, bards must have a mini-mum Spirit score of 4. In addition, they require a Presence score of at least 5 to hold an audience's attention.
!Advantages:
As inveterate travelers and lore-lovers, bards most likely know a little bit about every important or mystic place on Ansalon. 'While visiting a significant site, a bardic hero enjoys a trump bonus to any Reason action he attempts to recall stories or songs he's heard about the place (the Narrator determines the action's difficulty).
Additionally, these effective story-tellers can hold an audience virtually in thrall with their tales:
!!Enthrall an Audience
''Difficulty'': Varies
''Action Ability'': Presence
''Opposition Ability'': Perception
''Comments'': Succeeding at this action while telling a story or performing a song means that characters within earshot become absolutely engrossed. During the performance, they fail to pay attention to minor events around them-such as heroes sneaking into an off-limits room, picking pockets, or quietly abducting someone at the edge of the crowd. The Narrator determines the difficulty according to the circum-stances. The listener who would be hardest to distract (highest Percep-tion, acute senses, etc.) provides the opposition.
Mishap: The listeners find the bard's Rendition unappealing or in poor taste. Their exact reaction depends on their disposition before the performance started. Friendly characters merely chide the hero, while hostile ones may attack him. Narrators can determine the listeners' reactions using the aura of a random draw from the Fate Deck.
Heroes with the proper training can adopt this role during play, although those from Ergoth or Saiffium should first attend their realm's bard college.
!Disadvantages:
Like their kindred spirits, the street performers, bards are frequently looked down upon by the rich and powerful. Although these heroes may perform at parties and festivals-sometimes for enormous sums-many Ansalonians disapprove of their lack of roots.
Consequently, bards never enjoy a trump bonus for Presence actions (other than when performing) involv-mg those with a wealth of 8 or higher.
The Barmaid
A barmaid works in an inn or tavern serving the customers. Those who fre-quent the establishment might consider her a friend-at least someone to whom they can vent their frustrations-while less savory persons who only happen by the establishment occasion-ally may view her as a potential sexual conquest. These heroes enjoy the unique position of keeping tabs on vir-tually everything happening in the community. Tika Waylan from the Dragonlance Chronicles first appeared in this role.
Note: Although servers in taverns and inns are typically female in the Dragonlance setting, males can assume this role as barmen.
Role-playing
Barmaids are used to dealing with a wide variety of people, from friendly guardsmen and locals to abrasive mer-cenaries and obnoxious drunks. They can skillfully switch from one emotion to another, depending on who they are interacting with, in order to gain infor-mation or another favorable result.
Requirements:
As their job revolves around interacting with others, barmaids must have a Presence code of "C" or better. Further, they cannot have a Strength code higher than "C," as barmaids typically do not have the time it takes to become weapons masters.
Advantages:
Everyone has to eat and drink some-time, and the common room of the local inn remains the central meeting point in many towns across Ansalon. This gives barmaids the unique ability to keep track of law enforcement activi-ties and underworld movement alike, just by seeing who's meeting with whom and how often. They also can identify the comings and goings of strangers to the area and gather all kinds of interesting tidbits while serv-ing drinks or wandering the common room-patrons, viewing servers as just another part of the scenery, often forget themselves and continue sensitive con-versations while the barmaid stands nearby, absorbing every word.
Barmaids become adept at dealing with people on a variety of levels and in a variety of situations. Whenever they interact with a character in a non--combat situation, any card played for actions to put on a false face (appear to the character as seductive, angry, friendly, frightened, or any other suit-able emotion) is automatically consid-ered trump. In melee combat-a bar fight, for instance-any card played for
The barmaid to wield an improvised weapon becomes trump as well. (See Heroes of Steel for details on improvised weapons such as chairs, tankards, or Tika's famous skillet.)
Heroes who begin work in a tavern or inn can adopt this role during play.
Disadvantages:
Although working at a community's central gathering point has its advan-tages, it has its drawbacks also, particu-larly for a hero leading a double life simple barmaid by day, daring rebel by night.
Whenever the hero encounters someone who frequents her inn or tav-ern in another setting, she must perform a Reason action to recognize him before he notices her. (This action's difficulty depends on how often the character has seen the hero.) If the player fails at this action, the character recognizes the barmaid, as follows:
* If she failed her target action score by 1 or 2 points, she looks vaguely familiar to him, but he isn't sure where he's seen her before.
* Failing the action by 3 to 7 points means the character knows that she doesn't belong here.
* Missing by 8 or more points tells the character exactly who the hero is and where he's seen her before.
The actions the character takes upon recognizing the hero will vary depend-ing on the circumstances. A quick-thinking hero might be able to bluff her way out of the situation.
|!Valores de Habilidades|!Códigos de Habilidades|!Otros Requerimientos|!Ventajas|!Desventajas|
|Agilidad 5 min, Destreza 5 min, Percepción 5 min, Espíritu 4 min|Percepción C min, Espíritu B min|Ninguno|Bono de [[Carta de Triunfo]] para acciones de Presencia con ciminales y ciertos hechizos de meditación o canalización; puede adoptar rol durante el juego|No puede obtener Bono de [[Carta de Triunfo]] en acciones de Presencia con Autoridades; No puede usar armas Muy Pesadas|
The Jester Role
Role-Playing
Jesters are comedians, clowns, tricksters. They make others laugh, they are completely insane and not serious. Their humor is sometimes dark, easy, simple or really deep. Not every of them dresses in joyfull costumes with bells and the usual stuff. They are often invited to Lords' Courts, nobles' parties or just in a simple tavern. They like adventures.. They can gain a lot of friends, money and of course, some new stuff for their next joke. They like to get new and weird clothes and stuff for themselves or for the play that they are writing. They prefer small easy-to-hide weapons and don't wear armors other than Very Light.
Requirements
This Role requires a minimum of 7 in Reason and a B Code in Presence. Also, a score of 5 in Dexterity or Agility is required. This Role is open for every races.
Advantages
The Jester gains a +4 bonus for every presence-related Action when they are in front of an audience. They gain the Acute Hearing bonus.
Disadvantages They aren't taken seriously. There is a -4 malus for every "dealing-business-related" Action.
The Chaos War and the tumultuous events that followed it shook the very foundation of the Knights of Takhisis (as described in Chapter Three of Dusk or Dawn). Many Knights took advantage of the confusion to quit the Order, which ordinarily would mean death at the hands of their former comrades. Though the Knights have never openly acknowledged such desertions, all members realize that escape from the Order is quite possible, though dangerous.
The rogue knight is a hunted fugitive hiding from both his former brethren and from the darker episodes of his past. A rogue knight whom the Order recaptures can expect a painful and humiliating death. At the same time, should anyone else discover his past, this hero could face execution, banishment, or even forgiveness depending on how well he has chosen his new friends and neighbors.
Dhamon Grimwulf, introduced in the Appendix of Dusk or Dawn and featured in The Rising Storm and The Dawning of a New Age, is a rogue Knight of Takhisis.
!~Role-Playing:
One might leave the brotherhood of Dark Knights for a variety of reasons. Because applicants who fail the required tests of loyalty meet with execution (see page 43), the hero might have doubted his ability to successfully petition for final induction to the Knighthood. Or perhaps he suspected he would not be judged fairly. A rogue knight might have grown disillusioned with the Order and its ruthless philosophy, or he could have learned just how much chicanery the Knights currently use to keep their members loyal. In any case, a hero playing this role undoubtedly has experienced and done things while a member of the Knighthood that he prefers not to talk about.
To most folk, a rogue knight seems like any other mercenary or adventurer. People usually are appalled to learn the hero's true past and will shun him unless he has proven himself to them. Elves particularly the Qualinesti, who have lived under the Dark Knights' thumb for thirty years find it hard to trust any for-mer Knight of Takhisis. The fact that some Dark Knights operate covertly these days often justifies people's suspicion of anyone known to have a connection with that Order.
!Requirements:
The rogue knight, as a trained warrior, possesses Strength and Endurance scores of at least 6. In addition, it takes a strong will to turn one's back on an organization as powerful and dangerous as this Knighthood, calling for a Spirit score of at least 5. A rogue knight, while naturally proud and imposing, remains ever wary of attracting too much notice. Therefore, his Presence score must fall somewhere between 5 and 8.
This hero's military experiences have given him a good knowledge of armor and weapons, requiring a code of "A' in both Strength and Endurance.
Though no longer preoccupied with physical combat, moSt rogue knights are not well versed in the powers of the heart or the mind. Therefore, these heroes' Spirit and Reason codes should not exceed "C" at the beginning of play. (Narrators may choose to make excep-tions for heroes who were once Skull or Thorn Knights.)
As anyone with this role was once a Knight of Takhisis, it is open to only humans and half-elves.
A rogue Knight of Takhisis has both a demeanor and nature based on cards with values of 5 or lower. In addition, heroes cannot begin playing this role with a wealth score higher than 3.
!Advantages:
A rogue knight knows his former comrades well. This background gives him an automatic trump bonus when combating Knights of Takhisis; any card he plays is considered trump for melee and missile attacks, surprise, and initiative, but not for artillery attacks. When attempting to impersonate a Knight of Takhisis, any card the rogue knight bids for a Presence action becomes trump as well.
The rogue retains a benefit from his days in the Knighthood: When riding a mount in battle, he receives a trump bonus for any melee range attack. As always, this benefit is not cumulative with the previous ones.
Heroes with this role become rogues only after realizing the mistake they made in joining the Knights of Takhisis. Only heroes abandoning the role of a Dark Knight can acquire this one during play, immediately after their desertion from the Order of dark paladins.
!Disadvantages:
The mental and spiritual scars from a rogue knight's time in the Order pain him still. Consequently, when resisting mysticism, no card he plays is trump.
Players should remember that the Knights of Takhisis never give up searching for members of their Order who have disappeared even if the rogue knight staged his own death. This hero faces certain execution if the Knights of Takhisis capture him and discover his true identity.
Although a hero can abandon the rogue knight role, he forever remains a fugitive from the Knights of Takhisis, no matter what he does.
Knight of the Skull
Ability Scores Ability Codes
EN 6 min EN A
ST 6 min ST A
SP 5 min SP B min
PR 5 min PR C min
Other Requirements: Human or half-elf only; demeanor 5 max; nature 4 min; quests 5 max.
Advantages
Trump bonus to close range, for spell attack vs Legionnaires, for mounted melee attacks, and to resist mysticism; +3 PR action bonus in negotiations.
Disadvantages
Dearth for failure at a Test of Takhisis or if found guilty of violating the Code; owes 40-60 days' service; difficult to acquire role during play.
The Knights of Takhisis divides itself into three orders. Each of the three emphasizes different aspects of the Code (a set of rules defining how a Knight should advance the interests of the Order). However, neither the Order of the Skull (which stresses spiritual power), Nor that of the Thorn (Dark Knight sorcerers) epitomizes a true warrior's role like the Knight of the Lily. The members of this order of Dark Knights, the death lily emblazoned on their armor, form the backbone of the Knighthood's formidable military power.
While the Dark Knights model their Order after the Solamnic Knighthood, they dedicate their lives to the Evil goddess Takhisis rather than the forces of Good. Even though she and the other gods have withdrawn from the affairs of Krynn, these Knights remain committed to world conquest in the name of their Dark Queen. Their continued brief glimpses of the Vision (believed to be her divine plan for her faithful) help them maintain their allegiance to the Blood Oath: "Submit or die."
The entry-level order within the Dark Knighthood, the Order of the Lily includes inducted Knights as well as squires who have yet to petition for Knighthood. Steel Brightblade, fallen hero of the Chaos War, was a Knight of the Lily.
!Role-Playing:
Like all Knights of Takhisis, a Knight of the Lily must live according to the Code: He must obey his superiors, respect all friends and honorable foes, and willingly sacrifice anything for the Order. The Order of the Lily stresses the value of obedience in particular, as well as the strength of the group (to be independent is to be weak).
Heroes entering the Knighthood must begin as squires in the Order of the Lily, demonstrating their loyalty before becoming full Knights. (See page 43 in book Night and Day for more information on this process.)
All Knights of Takhisis are reviled almost everywhere except in the land of Neraka, which they control, and in the various Dragon Realms. Nonhuman races almost universally detest the Dark Knights. Nevertheless, the Knights
have a reputation for honesty some of the dragon rulers employ them as mercenaries and constables.
Knights of the Lily usually do not make good additions to adventuring parties. However, many of them operate covertly, gathering information for their superiors. Whole parties of Dark Knights also roam the land, seeking glory and booty.
!Requirements:
A Knight of the Lily is trained for war, SO his Strength and Endurance scores most be at least 6. In addition, heroes with weak wills cannot follow the Code, nor can a Knight prove his loyalty without a strong character. Therefore, this role requires minimum Spirit and Presence scores of 5.
As Knights of the Lily must study the art of melee combat in preparation to fight and win any battle, heroes with this role must have Strength and Endurance codes of "A." However, a Knight of the Lily's emphasis on physical combat skills limits his initial Reason and Spirit codes to "C" or lower.
Only human and half-elf heroes can play the role of a Knight of the Lily, as only these two races may join the Knights of Takhisis.
Players must pay attention to the cards they select to determine a Lily Knight's personality. The hero's demean must come from a card with a value of 5 or lower, while the card describing his nature must be 4 or higher.
!Advantages:
A member of the Order of the Lily leads boldly and skillfully in battle. Any card he plays to close with the enemy automatically becomes trump.
However, a quality unique to Dark Knights is that they despise the Legion of Steel. After all, not only does the Legion dare to assume the name of one of the most honored Dark Knights, it was founded by Sara Dunstan, a traitor to the Order. Consequently, Knights of the Lily receive an automatic trump bonus for melee attacks against Legionnaires.
When riding a mount in a battle, any card a Knight plays for a melee attack becomes automatic trump. (This benefit is not cumulative with the previous one.)
If a hero with this role has a reputation below Adventurer when he begins play, he starts as a squire in the Order of the Lily. After a quest or two, when his reputation has advanced to Adventurer, he can petition for Knighthood in the Order of the Lily (see page 43).
A Knight of the Lily can appeal for advancement again after completing one quest; because all three orders within the Knights of Takhisis are equal, his reputa-tion rating need not improve one cate-gory as does a Solamnic Knight's. Should the Dark Knight's appeal succeed, he has three options:
#He can remain a Knight of the Lily and immediately attempt to improve his Presence score, as described at the end of Chapter One in the Book of the Fifth Age. A hero receives this benefit only once.
#He can become a Knight of the Skull and learn to follow the path of dark mysticism.
#He can become a Knight of the Thorn and pursue the role of an Evil sorcerer.
During his attempt to become a Knight of the Lily, a hero receives a personal version of the Vision, showing him his part in the future of the Knighthood. In game terms, the player draws a random card from the Fate Deck; depending on the card, the hero can receive a bonus to certain Presence actions. A Knight also can, at any time, receive information from his superior through the Vision. The workings of the Vision, are described more fully on page 38.
!Disadvantages:
A Dark Knight's honor is his life. Should a hero fail in his petition for Knighthood, the Order immediately puts him to death. In addition, a Knight of Takhisis can be called upon to answer for conduct deemed unbecoming a Knight (see page 44).
All members of the Order of the Lily are subjected to a rigorous mental examination by their superiors upon joining as youths. This experience wrenches the mind and drains the spirit, such that a member of this order never receives a trump bonus when resisting mysticism.
All Knights of Takhisis remain sub-ject to a rotating duty roster, which assigns them forty to sixty days of direct service to the Order each year. As in the case of cavaliers, the Narrator can devise a "duty" quest for a Knight of the Lily and his companions, or the Knight can simply leave play for a time.
To become a Knight of the Lily, a hero must join the order as a youth. No older hero can acquire this role -or join the Knights of Takhisis-during play. If a Knight of the Lily wishes to abandon this role, he must immediately begin playing the role of a rogue knight (see page 20).
"Ek'thik allus mot durnat"
"Goodness is best."
-Oath of the Knights of Hylo
History of the Knights of Hylo
In 1640PC, the citizens of Hylo established a new warrior regime. In awe for a long time over the Knights of Solamnia, with all their shiny armor and bright weapons, a large group of kender took it upon themselves to form a kender knighthood. Calling themselves 'The Knights of Balif', the kender ran amok, wielding short swords and spouting rules that sounded just and fair in imitation of the knights they so admired.
Eventually, word was passed of these events to the Grand Master at the time, a strict man named Gregori uth Telan. Thinking that the kender were attempting to mock the knighthood with their ridiculous antics, the Grand Master sent an emissary to Hylo to order the kender to cease and desist. The emissary returned with rather unexpected news. The kender had refused, and had instead, sent an invitation for the Grand Master and any knights with him to become honorary members of the Knights of Balif's most prestigious order, The Order of the Acorn.
The Grand Master was infuriated by this and ordered an invasion of Hylo, heedless of his advisors recommendations against such action. The kender never even realized that they were being invaded when the knights marched on the city, believing the Solamnics had indeed come to be Knights of the Acorn. With incredible jubilation, the kender greeted the knights, swarming around the enemy camp and causing chaos in general. After three weeks of this "siege", the commander in charge of the invading force, a man by the name of Markus uth Wistan, held an audience with Hylos Elder's Council. Calmly, the knight explained that the Grand Master felt like the kender were making sport of the knighthood. While the council did not understand what was meant by mockery, they did realize that they had somehow managed to deeply hurt the Grand Masters feelings, and so the kender knighthood was dissolved.
This did not mark the end of the knighthood however. In 349AC, a small province in Goodlund called Pouchstrap, the Elders Council met to form a new fighting regiment to oppose the then invading dragon armies. Under the council of Delnik Springfingers, the Council revived the old knighthood of kender. Wary of the situation and keeping in mind the circumstances and occurrences of the last time the knighthood was introduced, the council worked to make the Knights of Balif more versatile and more non offensive. Thus were born the Knights of Hylo, in honor of region that first established the knights. These knights did not go out of their way to look like knights and created their own rules instead of borrowing those of the Solamnics. Although many kender joined the Knights of Hylo, the orders recreation was too late to help stop the dragon armies' invasion of the kender lands. Instead, the knighthood attacked the occupying forces with impunity. The downfall of Toedes forces in Kendermore is credited to not only death of the highlord, but also the definite presence of the Knights of Hylo.
During the Summer of Chaos the Knights of Hylo that were present in Goodlund during the occupation were put in charge of finding a way to expel the Dark Knights from the Kenderwood, but the arrival of the Chaos beasts prevented that and they fought side by side with the occupying forces against the beasts. They were also present at the destruction of Kendermore and were credited for their part in assisting in the Kender Flight and holding back the marauding forces of Malystryx.
How the Knighthood Works
The knighthood itself has but one rule: To always work for good. The knighthood teaches the vow amongst its members, the kender phrase 'Ek'thik allus mot durnat' which means 'Goodness is best'. Each and every knight works wholly towards this end, but in different ways, depending on the order to which they belong.
Kender of the Pouch: The members of this order, like their namesake, are those who hold many things. Their involvement is minimal, but they are by far the most numerous. They act as information gatherers, fund raisers, as providers of safety, and in times of need, an extra hoopak in battle. They tend to be kender who have already settled down in a community, as this type of work is ill suited to a kender struck with wanderlust.
Kender of the Sparrow: Like the bird, this knighthood wanders freely, with mirth and cheer. These knights are often kender just struck with wanderlust, out adventuring and wandering in search of whatever is interesting. A kender of this order not only gathers information, but is a general good deed doer. He lives to right wrongs wherever he may find them, and thus usually getting into no end of trouble. Some kender joke that like the sparrow, this order must quite frequently take flight. Regardless, Kender of the Sparrow are by far the strongest of their race, and there is no denying that their ability to use weapons effectively is unrivaled by any of their race.
Kender of the Hoopak: The Kender of the Hoopak dedicate their lives to the furthering of good. These kender are like the hoopak: straight and tall, supple and strong. These kender are often on the Elders Council in their region, the leaders of the community. Kender of the Hoopak are often chosen to represent the kender as ambassadors to other nations, as emissaries and delegates. Also amongst their ranks are those few kender who will never lose the tinge of Wanderlust, those who will continue to wander until their dying days and those who have gained much respect from other races. This final order is the defining power of the knighthood, the members well known for their cunning and wit, for their intelligence and their way with words.
Unlike the Solamnic Knights that have strict guidelines on the type of person which may be a knight, the Knights of Hylo feel that any kender that is true of heart and can wield a hoopak can be part of the organization. They even include honorary members among their ranks of humans, elves and dwarves, but these cases are rare and sometimes an unexpected surprise to the honorary member themselves.
In true kender fashion the "orders" themselves are not actually in any particular order and belonging to one over another does not always begrudge any more respect. It is merely an indication of the type of work that kender does in the organization. Experience in the knighthood is the ruling factor in most cases as to which member out ranks another. A Kender of the Hoopak council elder may grudgingly accept the recommendations of a Kender of the Pouch if the kender has more experience in the organization. A kender may switch orders as they see fit. There is a formal council for the Knights of Hylo, but it is as transitory as its members. They are called together in times of great need, but in most cases the knights are free to do as they will to bring goodness to the world.
As lordly titles seem important to the Knights of Solamnia they seem equally important to kender knights. The title of a kender knight is a summary of their accomplishments and incorporate tales of their exploits and adventures. Their titles may change from day to day or even meeting to meeting depending on the situation. Some example titles are: "Sir Delbin Gnomeflinger Destroyer", "Lord Telik of the Minotaur Chase" or "Lady Simpra Uth Fun of the Dragon Isles and Beyond". The grander sounding the name, the more impressive they are considered among other kender knights.
There is no standard uniform for the Knights of Hylo as each kender has their own particular tastes and the idea of lounging all day in a suits of full plate mail are not on the top of many kenders lists. As such each Kender Knight does bear an emblem, broach or patch with the symbol of their current order. There is the Purple Pouch for the Order of the Pouch, the Orange Sparrow for the Order of the Sparrow and the Silver Hoopak for the Order of the Hoopak. These emblems are displayed proudly and they are just as much a part of a kender as her hoopak, they are something that is never lost or given away.
The Knighthood Today
Today the knighthood is based solely in Hylo, although Knights of the Sparrow still fly to the farthest reaches of the continent. It is ruled from Hylo by Sarha Truehand and a council of elder knights. The knights continue to promote goodness around the world and do their best to help those in need. Afflicted kender have added a new facet to the kender knights. The true kender have been wary of allowing their dour faced cousins into the knighthood. Many afflicted kender refuse to even enter as they believe that people should handle their own problems without interfeance, but occasionally there are those afflicted kender that truely have a longing to assist those in need and they are monitored closely by their peers to make sure they stay true to the ideals of the knighthood.
Belladonna has long sought to make the Knights of Hylo into a standing army, but that is near impossible to achieve as each kender knight has a duty to assist the weak and defenseless, two things that the leader of Hylo is definitely not. The organization does what it can to further the cause of righteousness and now that the gods have returned it is not uncommon to find followers of Fizban or Branchala among their ranks spreading the good word and performing good deeds for those less fortunate.
Hit Die: d8
Requirements
To qualify to become a Knight of Hylo, a character must fulfill the following criteria
Race: Kender
Alignment: Any Good
BAB: +4
Ability: Evasion
Skills: Bluff 4 ranks, Diplomacy 2 ranks, Gather Information 2 ranks
Feats: Lightning Reflexes or Weapon Focus (any kender weapon)
Special: Must be sponsored by an existing Knight of Hylo and proven themselves worthy by committing a good deed, no matter how small or how large.
Class Skills
The Knight of Hylo's class skills (and the key ability for each skill) are: Appraise (Int), Balance (Dex), Bluff (Cha), Climb (Str), Craft (Int), Concentration (Con), Diplomacy (Cha), Disguise (Cha), Escape Artist (Dex), Gather Information (Cha), Hide (Dex), Intuit Direction (Wis), Jump (Str), Knowledge (all skills, taken individually) (Int), Listen (Wis), Move Silently (Dex), Perform (Cha), Pick Pocket (Dex), Profession (Wis), Scry Sense Motive (Wis), Swim (Str), and Tumble(Dex).
Skill points at each level: 4 + int modifier
Knight of Hylo
Class LevelBase Attack BonusFort SaveRef SaveWill SaveSpecial1st+1+2+2+0Valiant Talent 2nd+2+3+3+03rd+3+3+3+1Valiant Talent4th+4+4+4+15th+5+4+4+1Valiant Talent6th +6/+1+5+5+27th +7/+2+5+5+2Valiant Talent8th+8/+3+6+6+29th+9/+4+6+6+3Valiant Talent10th+10/+5+7+7+3Protection from EvilClass Features
The following are class features of the Knight of Hylo Prestige Class.
Weapon and Armor Proficiency: The Knight of Hylo a is proficient with all simple and martial weapons. They also gain a proficiency with one of the following kender weapons bollik, chapak, hoopak, sashik, sithak, whippik or yothak.
Valiant Talent: At every odd level, a Knight of Hylo may take a Valiant Talent. Normally a character will select from the talents for their order, but they are free to choose a talent from any of the orders listed below. Each talent can only be selected once. See the Valiant Talents charts below.
Protection from Evil (Su): At 10th level the knight gains a permanent protection from evil upon themselves that works as the spell.
Valiant Talents
Order of the Pouch
Intelligence Gathering (Ex): "When you arrive some place new see what you can find in the way of hospitality and information." The knight gains a +2 competence bonus to Pick Pockets and Gather Information checks.
Spot Entrance (Ex): "Many human cities are built without taking kender into consideration, so know how to get into and out of town." The knight gains a +4 bonus when searching for anything that would allow entry into or out from a location, (Doors, cracks in a wall, sewer pipes, chimneys, dumb waiters, coal chutes....)
Hard to Hold (Ex): "A Knight of Hylo should always be upstanding and never handled like a common thief." The knight gains a +2 to Escape Artist checks and +4 on opposing grapple checks
Fast Draw (Ex): "Be quick on the draw. You need to be fast to save lives." The knight can draw pouch items with astonishing speed. She can draw any item from her pouches as a free action instead of a move action.
Hide in Plain Sight (Ex): "Be nippy and nimble to keep your charges safe." The knight has become so adept at running away and dodging authorities, merchants and other pursuers that they may make a Hide skill check while moving at normal speed with no penalty. While running, they only incur a -10 penalty when using the Hide skill check.
Order of the Sparrow
Weapon Knowledge (Ex): "Don't hit your enemy with the wrong end of the stick." The knight is using a bollik, sashik, or whippik they gain the Weapon Finesse Feat. If they are proficient in chapak, hoopak, sithak, or yothak they gain the Weapon Focus Feat. If they are proficient in one of each they can select the feat to use.
Improved Feint (Ex): "Always keep them guessing about where your coming from." The knight gains a +2 bonus to his Bluff checks when he attempts a feint. He also feints as a move-equivalent action instead of a standard action. The knight cannot use this ability while wearing medium armor or heavy armor.
Quick Draw (Ex): "Make sure you're ready before they are." The knight gains the Quick Draw feat for free.
Sure-Footed (Ex): "When the enemy is about keep your eyes open, your ears open and your mouth closed." The knight is never flat-footed even when surprised. The knight cannot use this ability while wearing medium armor or heavy armor.
Combat Reflexes (Ex): "Always strike them hard and fast." The knight gains the Combat Reflexes Feat for free.
Order of the Hoopak
Kender Luck (Su): "Sometimes it takes a little luck to get what you want." The knight has an unusual knack for saving her neck in dangerous situations. Once a day on any roll she may opt to have a re-roll. The outcome of the re-roll must be used instead of the original roll.
Kender Diplomat (Ex): "Keeping your hands out of other people's pockets is a sure way to impress them!" The knight gains a bonus to the skill Diplomacy equal to his Knight of Hylo level.
Undaunted (Ex): "Never give up. Never give in." The DC of any Intimidate skill checks used on the knight is raised by +10.
Observe Motive (Ex): "It's surprising, but sometimes other races fail to be completely honest!" The knight gains a bonus to the skill Sense Motive and Bluff equal to half his Knight of Hylo level, remainders rounded up.
Kender Charm (Su): "Keep on smiling and everything will turn out fine." The knights Charisma is raised by +1.
Acknowledgements
Steve Miller – For Heroes of Definance and creating the back story of the Knights of Bailfor.
Tavin Springfingers – For bringing the Kender Knights back to life, writing the inital description and creating the different orders.
[>img[Arte de atongwali en www.dlnexus.com|http://www.dlnexus.com/gfx/art/11424.jpg]]
Sus tierras ([[Solamnia]]) originarias han cambiado mucho en los últimos tiempos. El Señor Dragón [[Khellendros]] tiene sus dominios sobre gran parte de ésta región. La orden sigue trabajando por sus antíguos valores bajo el liderazgo de Sir Liam Ehrling, tras la muerte de Sir Gunthar Uth Winstan.
Ha habido cambios en el funcionamiento interno de la orden. Uno de ellos consiste en una relajación de los requisitos de aceptación de aspriantes a caballeros. Ahora no sólo se permiten miembros de otras razas, sino también mujeres. En particular, se ha permitido la entrada a sus filas, de medio-elfos.
Otro de los cambios consiste en la inclusión, entre sus filas, de miembros encargados de dos actividades antes prohibidas a los caballeros: el espionaje, y la hechicería. En particular, los hechiceros reciben el título de [[Hechicero Auxiliare Solámnico|Rol de Hechicero Auxiliar Solámnico]].
Ariakan, hijo de Lord Ariakas, pasó gran cantidad de años en prisión, bajo la custodia de los [[Caballeros de Solamnia]]. Allí aprendió su mística, reglas, procedimientos y costumbres. Encontró que la razón de la pérdida de las batallas en nombre de la diosa Takhisis estaba en la poca disciplina y lealtad de sus combatientes. "El mal se torna contra sí mismo", se decía entre las "fuerzas del bien". Durante la [[Guerra de Caos]] Ariakan murió, pero la orden de caballeros oscuros creada por él, los Caballeros de Takhisis, continua siendo una fuerza de mucho poder en el continente de [[Ansalon]]. Sin embargo, el elemento unificador de la orden: la [[Visión]] dada por Takhisis a todos sus miembros, ya no guiaba sus actos. La diosa permanecía, al igual que el resto de los dioses, en un absoluto silencio ante las plegarias e invocaciones. La orden empezó a perder su orden interno y finalidad primigenia. Grandes facciones de Caballeros de Takhisis se encontraron de "cuidadores" de los terrenos bajo dominio de los Señores Dragones. Otros deambulan en grupos, infundiendo miedo y ganando dinero e influencias con sus acciones bélicas. A veces el dinero es ganado para la orden. A veces no.
La Governadora General de los Caballeros de Takhisis es Mirrielle Abrena. Ella ha dado un impulso a la orden para invadir el [[Salvaje Este]], y [[Nordmaar]]. Mucho del antíguo orden se ha perdido, así como el respeto al "honor" y "moral" de la antigüa orden, con el aumento desmesurado del reclutamiento poco selectivo. Esto ha ocasionado la deserción de numerosos caballeros "a la antígüa", que son denominados [[Caballeros Vagabundos]]. Existe una pena de muerte por el crimen de deserción que han cometido los [[Caballeros Vagabundos]].
Pese a que la orden ya no cuenta con [[Clérigos]] en la [[Orden de la Calavera]], ni con los antíguos hechiceros que conformaban la [[Orden de la Espina]], ambas órdenes siguen existiendo, nutriéndose de caballeros con talentos en [[Misticismo]] y la nueva [[Hechicería]], respectivamente. La [[Orden de la Calavera]] ha dedicado gran parte de sus estudios místicos a desarrollar el arte del [[Mentalismo]] y la [[Necromancia]].
La Governadora General ha conformado, con los caballeros de más alto rango de la [[Orden de la Calavera]], la llamada [[Cábala del Corazón Puro]]. Ésta se ha encargado de usar el [[Misticismo]], no sólo para implantar imágenes mentales que pretenden ser la antígüa [[Visión]] que recibían los caballeros directamente de la diosa [[Takhisis]], sino para leer las mentes y corazones de los caballeros. Esta sección es liderizada por [[Sir Galen Nemedi]], un experto Necromante. Las mentes y almas de los caballeros son regularmente "escaneadas". Si algún pensamiento o sentimiento potencialmente conducente a la traición o deserción de la orden, el caballero es capturado y desaparecido sin rastro.
----
Knights of Takhisis
An Order of Dark Knights formed some 20 years ago after the downfall of Neraka, the stronghold of the dragonarmies during the War of the Lance and the center of influence for Takhisis, the Dark Queen. In the years after the War of the Lance, the Knights of Takhisis quickly emerged as a cohesive force of order (and evil) in a world still reeling from years of war.
Organization
From the day he founded his Order of Dark Knights, Lord Ariakan, the son of Halyard Ariakas and (bards say) the goddess of tempest, Zeboim, stood strong as it's single guiding force. He ruled the Knighthood through his own personal magnetism and the Dark Queen's favor.
Today, Mirielle Abrena (Governor-General of Neraka and the Knights of Takhisis) maintains the highly military structure Ariakan favored. She makes changes only as necessary to allow for the growth of the Order and its holdings.
Divisions and Offices
Like the Solamnics, from whom Ariakan gained his inspiration, the Dark Knighthood is divided into separate groups. However, unlike the the Knights of the Crown, Sword, and Rose, these orders all enjoyed equal status within the Knights of Takhisis from the beginning. In addition, each division has a specialty: the Order of the Lily comprises warriors, the Order of the Skull includes dark mystics, and the Order of the Thorn contains exclusively sorcerers.
Lord Knights
Lord Ariakan administered the Knights of Takhisis with the help of 24 Lord Knights, and Governor Arena continues this tradition. Lord Knights win their positions by merit, usually through force of arms; dueling to obtain an office is not only allowed, it is encouraged.
Three Lord Knights hold responsibility for the three Orders. However, these figures may only give orders to their individual orders; military and other commands remains the duty of the commanders of the individual military units within the Knighthood.
For example, the Lord Knight in charge of the Knights of the Thorn, can instruct the Gray Robes on the proper way to deal with captured sorcerers and their magical items. However, individual Thorn Knights must answer to their military commanders when in the barracks or on the battlefield.
The other 21 Lord Knights who led the Knighthoods armies during the Summer of Chaos, handle special assignments, such as administering the city of Palanthas for the Blue Dragon, handle the daily business of governing the Dark Knights' capital, or overseeing the recruitment efforts.
Military Structure
All Dark Knights, regardless of their order, assume positions in a Talon (a unit of nine knights in the same order). The chart below shows the breakdown of the military units.
Unit Complement
Talon 9 Knights
Wing 5 Talons (45 Knights)
CompGroup 7 Wings (315 Knights*)
Shield 5 CompGroups (1,575 Knights)
Quadron 4 Shields (6,300 Knights)
Army 7 Quadrons (44,100 Knights)
* Also contains between 30 and 40 support staff members.
Today there is no structure above CompGroup because the Dark Knights are small enough to have individual CompGroups handle most daily affairs.
These CompGroups contain 4 Wings of Lily Knights, 2 Wings of Skull Knights, and 1 Wing of Thorn Knights. But, of course, if the Dark Knights take the field again in force, they would use the full military structure described above.
Rank and Precedence
Though personal reputation remains important, the Dark Knights base one's standing within the Knighthood Solely on military rank. A Talon Knight-Officer out ranks common Knights (even those of superior reputation categories). A Wing Sub-Commander outranks all his subordinates, as well as common Knights and junior officers from other Wings, and so on.
The Vision
In simple terms, the vision is a statement of the ultimate goal of the Knighthood as it pertains to each individual member. The Vision shows each Knight a subjective view of his part in achieving this goal: the total and unquestioned domination of the entire world of Krynn.
Before the Chaos War, all Dark knights relieved a personal version of the Vision, which they could consult for guidance when faced with difficult problems. No one knows if it came from Takhisis or her clerics. However, all the Dark Knights lost their personal Visions during the Chaos War.
Today, the Dark Knights still receive a Vision. However, they see it only upon their induction into the Order and on other rare occasions. The image it provides is vivid but short-lived, and its meaning often proves hard to fathom.
The Vision in the Fifth Age is actually the work of the Dark Clerics. With no assistance from Her Dark Majesty, they used Mentalism to convince the Knighthood of their Goddess's plan to return. This Vision inspired the ranks with new hope and determination, just as Arena had intended.
Due to the nature of the Vision in the Fifth Age, Knights can not consult the Vision at will. Instead it is at the Order's will. The true source of the vision is only known to senior commanders and the upper echelons of the Order of the Skull.
Communication Through the Vision
Now and again, information is sent through the Vision to the Knights. The Knight commanders might send simple missives consisting of a single image of a person, place, or thing and a verbal message of 25 words or less.
The Blood Oath
The Blood Oath is simple and straightforward: "Submit or Die." When each Knight joins the Order he dedicates his body and soul utterly to the cause. He must submerge any personal desires in favor of furthering the Knighthoods mission. Even today, when the Dark Queen seems more distant then ever, he knows she will reward him after death.
Yet, despite this sublimation of will, Dark Knights are expected to think for themselves at times. The Code guides them in their thinking.
The Code
The bulk of the code deals with establishing and maintaining communication and authority. It explains how a Knight gives an order and dispatches it quickly and efficiently.
Ariakan knew there would be times when his followers would be cut off from the chain of command. So he devoted lager sections of the Code to teaching them how to act on the Vision and how to carry out the will of the Knighthood on their own.
Order of the Lily
Independence breeds chaos. Submit and be strong. The Knights of the Lily provide the military might of the Order. The Knights of the Lily are both police and judiciary.
Order of the Skull
Death is patient, flowing from without and within. Be vigilant in all and skeptical of all. The Dark Mystics serve the Order as healers, diviners, advisors, and Adjudicators of the Code.
Order of the Thorn
One who follows the heart finds it will bleed. Feel nothing but victory. The Knights of the Thorn remain wholely committed to mastering new forms of sorcery and wielding their magic in support of the Knighthood.
Orders and Ranks
The Knights of Lily The Knights of Skull The Knights of Thorn
Petitioner
Supplicant
Follower
Believer
Warrior
Novice of Night
Night Acolyte
Night Warrior
Black Bard
Dark Wanderer
Dark Warrior
Warrior of The Lily
Master of The Lily
Protector of The Lily
Lord of The Lily
Lord of Night
-->
Bone Novice
Bone Acolyte
Bone Warrior
Skull Abbot
Skull Bishop
Skull Cardinal
Skull Knight
Skull Paladin
Skull Champion
Master of The Skull
Protector of The Skull
Lord of The Skull
Lord of Night
-->
Blood Novice
Blood Acolyte
Blood Apprentice
Thorn Apprentice
Sorcerer
Wizard
Seer
Master
Nightlord
Master of The Thorn
Protector of The Thorn
Lord of Thorns
Lord of Night
Author: Andrew Berrigan (aberriga@cnu.edu)
Changelings are people who use their skills in sorcery and in mysticism
to transform themselves and their environment. They make natural spies
because of their amazing talents, and can be either formidable enemies
or powerful allies.
Role-Playing
The changeling hero can blend in almost anywhere. He can walk amongst
the elves as an elf and walk amongst the minotaurs as a minotaur.
Changelings always hide their true pasts and keep their own hidden
agendas. Only their closest friends and companions should ever know
that they are changelings, because it is in a changeling's very nature
to live many lives. As for exactly what the changeling is after, only
he knows, but it is this very goal that kept him from pursuing other
schools of magic or mystical spheres during his days of training, and so
ultimately, all of his major actions must somehow help him achieve this
goal.
Requirements
Changelings have spent time in many foreign cultures and people in
order to learn how to walk amongst them unnoticed. To reflect this
experience, changeling heros must start out with at least 6 quests. In
order to blend in, he does have some natural talent at disguise, so he
must have a score of at least 6 in Presence. His true strength,
however, lies in his magical powers. Every changeling must have a score
of at least 7 and a code of A in Reason and Spirit. He must choose to
be proficient in Spectramancy, Transmutation and any one other school of
sorcery as well as the mystic spheres of Alteration, Channeling and
Meditation.
While none of his numerical scores are limited, a changeling can never
have an ability code greater than B in any ability other than Reason and
Spirit. This reflects how much devotion he has given these two forms of
magic.
Civilized humans, elves and half-elves can be changelings.
Advantages
Whenever a changeling uses the sphere of Alteration to change his
appearance, he may double the duration of the spell without affecting
the difficulty score (as listed on p. 76 of Book of the Fifth Age).
Upon creation, a changeling hero may choose any five realms listed in
Dusk or Dawn to be familiarized with. Any attempt to blend into these
areas using a normal disguise receives an automatic trump bonus, unless
the hero doesn't resemble the populace (i.e. a human changeling won't
resemble a kender no matter how much make- up he uses). If he opts to
use his powers of Alteration instead, the attempt becomes an automatic
success.
A hero must choose this role at creation, and cannot acquire it during
game play.
Disadvantages
Every changeling has a reason for devoting so much of his life to his
powers of transformation and blending in. Whatever this reason is, it
infects every part of the changeling's life. Secretly, he always works
toward this goal. Changeling heros never tell anyone what this goal
is. Consequently, if a character discovers that the hero is indeed a
changeling, he may mistrust him or even become hostile (other heros may
act as they wish).
Upon creation of a changeling, the player and the Narrator must decide
upon a goal. This should be something that is not easily accomplished.
If the Narrator ever feels that the hero is not working towards the
goal, he may make an action check. Success means the hero remains a
changeling, but must shape up his act. Failure means he must abandon
the role, never to get it back. It is up to the Narrator to decide what
a mishap would signify. If the hero actually succeeds in achieving his
nearly impossible goal, then he may choose a new role while keeping all
the advantages of a changeling.
If, in order to complete a disguise, a changeling needs to use a
shield, suit of armor or weapon that is normally outside of his skill
range, he is allowed to wear them without penalty. If he ends up in
combat with these items, however, then every combat action must be a
random draw, and the unwieldy shields and armor not only offer no
protection, but also reduce all agility action scores by 2.
Si se utiliza para una [[acción|Ejecutando Acciones]], la carta de la [[pinta|Pinta de las cartas]] correcta, se le permite al jugador sacar una nueva carta del mazo y añadir el puntaje a su acción. Si la nueva carta también es de la [[pinta|Pinta de las cartas]] apropiada, se saca otra.
También se obtiene una Carta de Triunfo si el tipo de acción realizada la recibe como bonus por raza, por rol, o por decisión del DM.
__Ejemplo:__ Los [[Elfos Kalanesti]] siempre reciben una Carta de Triunfo al utilizar cualquier tipo de arco, sin importar la [[pinta|Pinta de las cartas]] de la carta.
Este método implica que para un chequeo de una acción de un personaje (o NPC) el narrador saca una carta aleatoriamente del mazo del destino. Es muy utilizado para los chequeo de personajes sin jugador (NPCs).
El resultado de las acciones de los héroes es determinado, a diferencia de otros juegos de rol en los que se usan dados, mediante el uso de las Cartas del Destino.
Cada carta tiene:
*Un valor entre 1 y 10
*Un color que puede ser blanco, rojo o negro
*Una "[[pinta|Pinta de las cartas]]" (//suite//) que está asociada a alguna de las habilidades o al caos (//suite// de dragones)
*Un personaje famoso o relevante de las historias de DragonLance
*Un par de palabras que describen la personalidad del personaje de la carta
Estas propiedades de la carta pueden ser usadas de diversas formas por el Narrador para determinar el resultado de las acciones y el curso de la historia.
The Bounty Hunter
By Eric Jwo
In the wake of a new age, there are those that tread the fine line
between good and evil. A few men and women live on the outside
fringes of civilization and the border of morality.These men and
women fill a necessary occupation and bring their own brand of law
and order to the land.
Bounty hunters are like skilled mercenaries, only they aren't paid to
fight. Instead, they're paid, and paid well, to find and retrieve those
who don't necessarily want to be found. The Knights of Takhisis
typically send a talon of Lily Knights after any people that they are
after. However, since all rogue knights are familiar with the
procedures of the Knighthood, the Dark Knights often resort to hiring
bounty hunters to retrieve those who have left their Order. The Legion
of Steel uses bounty hunters a lot to track down those who cause
trouble. Indeed, many bounty hunters are asked to join the Legion if
they do a good job. While the Knights of Solamnia detest resorting to
hiring ruffians, they occasionally use bounty hunters to bring in
criminals.
Role-Playing
Bounty hunters are known as loners. Since they spend so much of
their lives on the border of lawlessness, with danger always a step
behind or ahead of them, bounty hunters don't like to make too many
friends. According to bounty hunters, it's better not to know the name
of the person you had to kill or the family of someone you'll one day
have to bring in. Since he is unable to get close to others, a bounty
hunter lives a closed off life, causing others to view him as an
uncivilized savage. A bounty hunter's lonely life also accounts for the
rather brash and rough way that he carries himself.
A bounty hunter acts tough and brash because he knows that any sign
of weakness could spell his death. A bounty hunter doesn't place
much stock in pleasantries, preferring action to talk. Often impatient
with others, a bounty hunter would not hesitate, at least not too much,
to leave a group at a moment's notice if he feels that everyone is just
sitting around.
Bounty hunters live only for themselves. They perform their work
because the money is good and because they are good at it. Like
mercenaries, money is what interests them more than anything.
Typically, a bounty hunter doesn't care about the dispute between his
employer and his prey, but some have been known to make moral
decisions. Still, for the majority of bounty hunters, money, not morals,
is the only thing that factors into a job.
Bounty hunters disdain heavy armor, but they don't like being
unprotected wither. Instead, they prefer functional leather or chain
mail. Since they spend so much time by themselves, they ahve a dirty,
savage look that many find disconcerting.
Some bounty hunters do have partners, but others believe that a
partner is just a liability. Rough and independent, bounty hunters are
the modern day heroes that fight for neither good nor evil in a godless
land.
Requirements
A bounty hunter needs to be physically fit in order to perform well.
Therefore, all Physical scores must be 5 or higher. Since bounty
hunters tend to be loners, thjey ahve a maximum Presence score of 5.
A bounty hunter needs to know how to fight in order to capture his
prey. Therefore, a bounty hunter has a minimum Strength and
Dexterity code of "C." A bounty hunter needs to be unburdened in
order to track down his prey. Therefore, he doesn't use armor or
shields as effectively as many others do. To reflect this, a boutny
hunter has a maximum code of "C" in both Endurance and Agility. A
bounty hunter also doesn't have any of the time or discipline that it
takes to master the mystic arts. To reflect this, a bounty hunter has a
maximum code of "D" in Reason, and a maximum code of "B" in
Spirit.
Bounty hunters can be of any race, but some, like elves, believe that
the occupation is too barbaric.
Advantages
A bounty hunter gets an automatic Trump bonus to any tracking
Perception action. A bounty hunter also gets an automatic Trump
bonus to create traps for their prey. Typical trap actions are average
- impossible Reason (Perception) or average - impossible
Dexterity (Agility) actions (according to the Narrator).
Disadvantages
A bounty hunter is a man of steel and wits, not magic. He does not
understand much of sorcery. To reflect this, a bounty hunter never
gains a Trump bonus to resist sorcery.
A bounty hunter manages to acquire many enemies during his lifetime.
Former employers, former prey, or even the loved one's of past
targets may wish to see the bounty hunter dead. The Narrator can
introduce these antagonists from time to time. For a more random
system, the Narrator can simply flip over a card from the Fate Deck
at the beginning of every new quest. If the card is a Dragon card, then
a former enemy shows up sometime in the adventure.
The dragonbane is a person who hunts down and kills dragons and draconians, and other wyrms. He is usually alone, since he prefers to do the killing himself. He is usually very secretive, and keeps to himself. He trusts no one, and usually has few friends. He hates all dragons, and dragon-kin. The secret organization of Dragonsbanes is a good example of this heroic figure, but a dragonsbane does not have to be a part of this organization to be a dragonsbane.
!Role Playing:
The dragonsbane believes that the only good dragon is a dead one. He hunts down and slays all dragons, draconians, bakali, behir, wyverns, and other wyrms. They hate every type of dragonkind, and have been trained to combat them. Good, metallic dragons are also considered "evil", but most
dragonsbane will not stalk or aggravate them.
Most humans see dragonsbane as valiant heroes to be respected. Dwarves and minotaur see dragonsbane as honorable and courageous heroes. Centaurs and elves see them as a little "unbalanced", and somewhat dangerous. Kender and gnomes view them as too darn serious.
!Requirements:
A dragonsbane needs to be tough and agile to be able to combat dragons. To reflect this, a dragonsbane hero must have a minimum score of 7 in Endurance and Strength, and a minimum score of 6 in Agility. A dragonsbane is a very imposing, and commanding figure. Therefore, they need a minimum score of 5 in Presence.
A dragonsbane is trained in the art of war. Therefore, he must have a code of "A" for at least two physical attributes. The other attributes cannot be lower than "C". Studying how to slay dragons limits a heros study of the metaphysical. Therefore, dragonsbane heroes cannot have a code higher than "C" in Reason, and cannot have a code higher than "B" in Spirit. Any race can play this role.
!Advantages:
Because of their training in with dragons, dragonsbane get an automatic Trump bonus for any action dealing with dragons and dragonkin. This includes resisting dragonawe, fighting dragons and dragonkin, and repelling dragon and dragonkin attacks.
!Disadvantages:
Dragonsbane can never learn these spheres: Alteration, Meditation, Necromancy, Sensitivity, and Spiritualism. Dragonsbane also don't trust magic. They must make an average Presence (Reason) action to use any non-dragon related magical item, or accept the help of a mage. Magical items intended to slay dragons are exempt from this action. They must also make a daunting Presence (Physique) action to resist attacking any dragon they see. If the dragon is good, or his friends are in danger, then a player can forego this action, or lesser the degree by two, whichever the Narrator would prefer.
Centaur Shapechanger
Abitility Scores Ability Codes
EN 7 min DX A
ST 7 min EN X
RE 7 max SP B min
PE 7 min (Alteration skill based on code)
SP 6 min
Other Requirements: Centaurs only; quests 3 max; alteration sphere required.
Advantages
Trump bonus using bows; soothes horses; trump bonus for alteration magic used on self; mobility advantages.
Disadvantages
No trump bonus for spellcasting (except alteration on self); assumed DX code of X for any missile weapon but bow; no trump bonus for PR actions with own clan; can adopt role during play only as first mystic role.
Centaur Wrestler:
The centaurs value their skilled warriors. Mastering the use of bows and the arts of fighting are essential attributes to a young male centaur, especially during the Age of Mortals. But the traditional ways of fighting are still considered important, and the centaur wrestlers are the masters of these combat arts.
To be a Centaur Wrestler, a hero must be a Centaur. No other races have the strength and the speed to execute the complex fighting maneuvers and techniques a centaur wrestler uses. Endurance and Strength must be at least 8 each, Perception should be at least 7, and Reason must have 6 as its maximum value. The maximum code allowed in Reason is C, and a Dexterity code of A is also necessary. As all centaurs, the code for Endurance must be X.
Centaur wrestlers receive a trump bonus when attacking with bows; they also receive trump bonuses to soothe horses and to fight on unarmed combat. They never receive trump bonuses for spellcasting or other missile weapons that are not bows. They can use special fighting maneuvers to drag a foe to the ground or to knock out a target by making a Challenging (12) Strength action, resisted by the foe's Endurance. Charging attacks are always trump for Centaur Wrestlers.
[img[Imágen de http://community.wizards.com/go/thread/view/75882/19913330/What_Art_Gets_It_Right_Pt_2!!&post_num=48|http://www.wizards.com/dnd/images/Monster2_gallery/34.jpg]]
!Requerimientos
*Valor Mínimo 7 en Resistencia (End), Fuerza (Str) y Percepción (Per)
*Valor Máximo 7 en Razonamiento (Rea)
*Código de Destreza (Dex) A, y Resistencia (End) X
!Ventajas
*[[Carta de Triunfo]] para ataques con arcos.
*Pueden calmar a caballos y afines
!Desventajas
*Nunca obtendrán [[Carta de Triunfo]] conjurando hechizos o mantras.
*El código de Destreza es X, salvo para los arcos.
"And I tell you, one more of your furry-elephant, teleporting ring, plants-living-off-air stories and I'll twist that hoopak around your neck!" -Flint, from Dragons of Spring Dawning
"Uh, I seem to have forgotten something. What was my name again?" -Fizban, from Dragons of Winter Night
"All I know is I've drowned twice, stricken with a deadly disease" -Flint, from Dragons of Winter Night
"Turn me into nothing, will you? Well you can take your nothingness and put it where the sun don't shine" -Tas, from Dragons of Summer Flame
"Why the beard? You were ugly enough." -Flint, from Dragons of Autumn Twilight
"Beats the hell out of me, Lady." -Caramon, from Dragons of Summer Flame
"We'll have to go out through the kitchen." -Tanis, from Dragons of Autumn Twilight
"Help! I've gone blind!" -Fizban, from Dragons of Autumn Twilight
"Idiot kender. Running off with a dead old man" -Flint, from Dragons of Winter Night
"Arrest the tree! Obstructing sunlight! That's the charge!" -Fizban, from Dragons of Spring Dawning
"Me? Splatter! I never in my life splattered!" -Fizban, Dragons of Winter Night
"No, my brother, where I go, you can not follow. Strong as you are, it would lead you to your death. We are finally as the gods meant us to be, Caramon- two whole people, and here our paths separate. You must learn to walk yours alone- or with those who might choose to walk it with you. Farewell, my brother." -Raistlin, from Dragons of Spring Dawning
"Good? Triumph? Not so, Half-Elven. The balance is restored. The evil dragons will not be banished. They remain here, as do the good dragons. Once again the pendulum swings freely." -Fizban, from Dragons of Spring Dawning
"Tanis… the constellations… gone! The constellation known as the Queen of Darkness and the one called Valiant Warrior. Both gone. She has come to Krynn, Tanis, and he has come to fight her. All the evil rumors we have heard are true. War, death, destruction…" -Raistlin, Dragons of Autumn Twilight
"Therefore I appoint to fill the position of leadership of the Knights of Solomnia, Lauralanthalasa of the royal house of Qualinesti-" -Lord Amothus, reading a letter from Lord Gunthar Uth Wistan, Dragons of Spring Dawning
"According to humans, half an elf is but part of a whole being. Half a man is a cripple." -Tanis, Dragons of Autumn Twilight
"Never heard of him. People are always mistaking the two of us, but I'm much better looking!" -Fizban, Dragons of Summer Flame
"I made love to a beautiful woman and didn't know it. Just my luck." -Raistlin, Dragons of Summer Flame
"No discipline in the younger generation. His father- now there was a puffball...." -Fizban, Dragons of Autumn Twilight
"Him more like two whole person." -Bupu, Time of the Twins
"He asks if you are to grand a elflord to paddle, because- if you are- he will allow your lordship to swim." -Silvara, Dragons of Winter Night
"Just tell me one thing. Why do they call it 'the River of the Dead'?" -Flint, Dragons of Winter Night
"Fizban. Yes..... I sure thought he was dead........" -Fizban, Dragons of Winter Night
"For the sake of my cold feet, I'd follow them into a dragon's den if he'd warm my toes!" -Flint, Dragons of Winter Night
"I killed him once, Tanis, I can do it again!" -Raistlin, Dragons of Spring Dawning
"I-I''ve had a-about enough of y-you, S-Sir High and M-Mighty." -Flint, Dragons of Winter Night
"I'm dead." -Tas, War of the Twins
"Just so long as he walks with me and doesn't try any fireball spells." -Tas, Dragons of Summer Flame
"We're not damsels, but we are in considerable distress, so I should think that would count. Don't you?" -Tas, The War of the Lance
"Uh, Fizban, your hat's on fire." -Tas, Dragons of Autumn Twilight
"I think Flint is feeling better, but he is not quite ready to eat anything yet." -Tas, Dragons of Winter Night
"May the Gods go with them." -Caramon, The Second Generation
"HE LOST THE DAMN GEM IN A GAME OF BONES!" -Dougan, The Second Generation
"Flint said thet? About me! I've had my uses in the past!" -Tas, Dragons of Summer Flame
"My queen..... it is your move." -Raistlin, Test of the Twins
"Me fly like big boss wizard!" -Rounce, Test of the Twins
"Take this key and keep it for all eternity. Give it up to no one- not even myself. And, from this moment on, your place is to guard this door. No one is to enter. Let death be swift for those who try." -Dalamar, Test of the Twins
"Farewell, Tasslehoff Burrfoot. I need not ask Paladine's blessing on you, for I know you are one of his close, personal friends....." -Crysania, Test of the Twins
"Oh, that is because I'm dead." -Fizban, Dragons of Winter Night
"I think it just occured to them that the women will probably be very greatful." - Dougan, The Second Generation
"Might as well invite the enemy inside for tea!" - Flint, Dragons of Winter Night
"And this is Raistlin's half-nephew. I think that's right. Let's see. Kitiara was Raistlin's half-sister. Perhaps that would make Steel only a quarter of a nephew-" - Tas, Dragons of Summer Flame
"You're going to be awfully glad you met me." - Tas, Wanderlust
"Mention not my daughter! I do not have a daughter." - Solostaran, Dragons of Winter Night
"I'll keep an eye on them. Do you have a problem with people stealing your mugs?" - Tas, Dragons of Winter Night
"Quit waving that sword around, Porthios! Someone'll get hurt." - Fizban, Dragons of Winter Night
"Come along, Solostaran, I'll help. We old men have to stick together. Too bad you're such a damn fool." - Fizban, Dragons of Winter Night
Besides, think how much trouble you'd get into without me!" - Tas, Dragons of Spring Dawning
"That got 'em! Wonerful spell, Fireball-" -Fizban, Dragons of Spring Dawning
"And that bridge is older than I am... and in worse shape." - Flint, Dragons of Spring Dawning
"I see... a man... who is not dying..." - Raistlin, Dragons of Spring Dawnig
"Home is someplace you say 'My, this looks just like it did when I left!' not 'My this looks like six million dragons flew in and wrecked the joint!'" - Tas, Test of the Twins
"Say, why are we throwing armor at Caramon, Tika? Is this something you two do regurally?" - Tas, Time of the Twins
"I wonder if we know the same Paladine..." - Tas, Time of the Twins
"Me know me not pretty, like lady lying there. But him not call me 'creature'! Him call me 'little one'." - Bupu, Time of the Twins
"I think this lady wants me to go to Kendermore and get married!" - Tas, Kendermore
"I don't think this man could make me mad enough to throw a pie at him, let alone a whole fiery mountain." - Tas, Time of the Twins
"Farewell, Revered Daughter. I need you no longer." - Raistlin, Test of the Twins
"As Granpa Tas would say, 'A chicken with it's neck wrung is different from a chicken with it's head cut off, but does it matter to the chicken?'" - Palin, The second Generation
"Keep him away! I always loved you, half-elf!" - Kitiara, Test of the Twins
"We will sing the hero songs ourselves." - Steel, Dragons of Summer Flame
"Tas! Palin, look! Here's his hoopak. It's... it's lying in a pile of... chicken feathers." - Usha, Dragons of Summer Flame
/***
|Name:|CloseOnCancelPlugin|
|Description:|Closes the tiddler if you click new tiddler then cancel. Default behaviour is to leave it open|
|Version:|3.0.1 ($Rev: 3861 $)|
|Date:|$Date: 2008-03-08 10:53:09 +1000 (Sat, 08 Mar 2008) $|
|Source:|http://mptw.tiddlyspot.com/#CloseOnCancelPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License:|http://mptw.tiddlyspot.com/#TheBSDLicense|
***/
//{{{
merge(config.commands.cancelTiddler,{
handler_mptw_orig_closeUnsaved: config.commands.cancelTiddler.handler,
handler: function(event,src,title) {
this.handler_mptw_orig_closeUnsaved(event,src,title);
if (!store.tiddlerExists(title) && !store.isShadowTiddler(title))
story.closeTiddler(title,true);
return false;
}
});
//}}}
Name: MptwRed
Background: #fff
Foreground: #000
PrimaryPale: #eaa
PrimaryLight: #c55
PrimaryMid: #711
PrimaryDark: #500
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88
Muchas acciones de un [[Héroe]] involucran combates. Las hojas de personaje listan armas que un personaje posee en un momento, pero podrían obtener otras durante sus viajes. Es potestad del Narrador decidir si un personaje puede o no usar un arma, basándose en los códigos de [[Habilidades]]. Generalmente, mientras más daño hace un arma, es más difícil de usar.
Hay dos tipos de combate:
*Combate a Rango o de Misiles: cuando los combatientes usan arcos, ballestas, hondas, o armas smimilares, están realizando un combate de Misil. A medida que se acercan, pueden usar armas lanzables como las hojas lanzables, shurikens, lanzas y dagas.
*Combate Cuerpo-a-cuerpo: Cuando los combatientes se acercan lo suficiente como para atacar con armas sostenidas en las manos como por ejemplo espadas, hachas, mazos, están involucrados en un combate cuerpo-a-cuerpo. Las peleas a manos libres (sin armas) también caen en esta categoría.
[[Rango de Combate]]
[[Secuencia de Combate]]
[[Acciones en Combate]]
Starting in 13sc, Goldmoon began dispatching Master mystics to the courts of Ansalon´s free realms. Although the mystics of the Citadel of Light were already starting to walk amog the people at that time, teaching the powers of the heart, Goldmoon knew the process would benefit if the land´s most powerful figures were sympathetic to the Citadel´s goals. To gain that sympathy, she needed to ensure that these leaders received her message without the filter of courtiers or the distortion of rumor. So arose the Citadel advisor, a Master mystic who teaches the powerful of Ansalon the final gift of the gods while dodging court intrigues and power ploys.
Much in the way the Citadel admits only those students whose hearts are inclined toward Good, Goldmoon sends advisors to seek positions only with rulers of good tendencies. (In realms whose rulers are deemed unfit for Citadel instruction, mystics move among the common people and hope for the best.)
It should be noted that Citadel advisors are perhaps the rarest of all the mystics represented by the roles in this section. The majority of Ansalonian rulers either have declined to permit a Citadel mystic to join their court or have not yet been approached about the matter. At present, Ciradel advisors are located in the realms of Gunthar (at the Castle Uth Wistan), Abanisinia (in Haven and Qué-Shu), Ergoth (in Gwynned), Solamnia (in Solanthus), Nordmaar (at North Keep), and on the Blood Sea isle of Saifhum (in Sea Reach).
Lady Crysania, Revered Daughter of Paladine, is one Citadel advisor. This aged woman dwells in Gunthar, where she advises the Lord Knights who guide the Solamnics.
Role-Playing:
Citadel advisors are self-assured smooth-talkers. They are used to dealing with some of Ansalon´s most learned and genteel individuals- as well as some of its most ignorant and crass, as the ranks of royalty include both.
Citadel advisors take their roles as “ambassadors” very seriously, even if they do frequently attend pleasant court social functions and grand balls. Although they never officially accept titles as lofty as “ambassador”, these heroes are the Citadel´s premier representatives at court. They are at once to provide rulers with spiritual guidance and to help them grow strong in the powers of the heart, as protection from those who would lead the monarchs astray or do them harm. Usually, the mistic´s temperament closely matches that of the ruler.
Requirements:
Generally speaking, the Citadel of Light cores nothing for a person´s background and history. The exception is the Citadel advisor. These individuals are chosen as emissaries to certain courts based as much on their heritage as on their purity of heart.
As advisors are charged with fostering an understanding of the Citadel and its Goals among Ansalon´s powerful, Goldmoon considers it important that these mystics are people the lords can respect. Therefore, all Citadel advisors must have a social status of Gentry (6) or higher. Mystics are always sent to the courts of rulers whose social status is equal to or one category higher than the mystic´s. Note that, using roles from Heroes of Defiance, a hero´s social status might not necessarily reflect his or her true high-born background (as in a hero switching from the displaced noble role to that of a Citadel advisor).
Like others in the fellowship, Citadel advisors have a Spirit score of at least 4. Unless stationed to a military post, they have little interest in weapons and battle; therefore they have Strength and Dexterity codes of “C” or lower and Agility and Endurance codes of “B” or lower. In addition, the advisor requires a Presence score of at least 4 to garner respect from members of the nobility.
Only Master mystics –those who have achieved Master reputation and defeated their persoal demons at the top of the Silver Stair- serve as advisors.
Finally, all advisors must have an “A” code in Spirit and, in addition to healing, practice mysticism from the sphere of sensitivity, to gauge the sentiments of courtiers and assist rulers in ferreting our potential traitors.
Advantages:
Heroes of this role are well connected among and well respected by members of Ansalon´s elite. Even lords who do not agree with the Citadel of Light typically acknowledge advisors as men and women of honor and high character. This respect among the upper classes means that any card played by advisors who are recognized as such becomes automatic trump for Presence actions to influence characters with social status of Gentry (6) or higher.
Heroes can adopt this role during play.
Disadvantages:
Although they sympathize with the plight of Ansalon´s poor and downtrodden, Citadel advisors are clearly not from their number. Members of the lower classes can recognize that this hero is a different kind of person than missionaries or other mystics and will react accordingly. Thus, cards played by advisors during Presence actions to influence the characters with a social status of Guildsman (5) or less are never considered trump.
The Dwarven Tunnel Builder:
During the Fifth Age, Thorbardin, even closed to strangers, is helping the Qualinesti elves in their fight against Beryl and the Knights of Takhisis by digging tunnels connecting their realms. To build reliable tunnels, the High Thane summons the tunnel builders, dwarven architects especialized in making safe ways and terrain identification.
To be a Tunnel Builder, a hero must be a dwarf. No other races have the required talents to identify soil types and possible cave-ins as the mountain dwarves. Hill dwarves are not so able to plan and build reliable tunnels, and therefore they may not be allowed to take this Role, unless they receive a special training to do so. Endurance, Strength and Perception must be at least 6 each, and Agility and Dexterity may have 8 as their maximum values. The maximum code allowed in Reason is B, and a Perception code of C or better is also necessary for a dwarf who intends to be a Tunnel Builder.
A Tunnel Builder receives a +2 bonus on all underground actions, even in combat. This reflects his/her ability in explore the environment resources at his/her will. Tunnel Builders consider all cards in actions as detecting secret or concealed doors, locating underground rifts, possible cave-ins or water sources, finding the directions in a tunnel and other actions related with the undergrounds as trump. However, no cards played in water situations as sailing or swimming are considered trump, and Tunnel Builders receive a penalty of -2 in open field actions.
*[[Convertir un Monstruo de AD&D a SAGA]]
*[[Convertir un Personaje de AD&D a SAGA]]
|!Coordinación|Movimiento / 2|
|!Físico|(HD x 3) + Modificador|
|!Intelecto|Inteligencia / 2|
|!Esencia|Moral / 2|
|!Daño|Daño máximo / 2|
|!Defensa|(10 - AC) / 2|
Siempre los redondeos son hacia arriba
#''Escoger Naturaleza y Comportamiento:''se debe seleccionar, de las [[Cartas del Destino]] las dos cartas que mejor describan el comportamiento del personaje, su alineamiento, y su personalidad.
#''Reputación'': el [[Número de Aventuras|3er Paso]] es idéntico al nivel del personaje en [[Advanced Dungeons & Dragons]]. Eso determinará el número de cartas y la reputación.
#''Estatus Social'': Puede asignarse de mutuo acuerdo entre el jugador y el narrador, o simplemente asumir que el número de cartas en la [[Mano]] determina el [[estatus social|4to Paso]].
#''Valores de las Habilidades'': existe una equivalencia entre [[habilidades de AD&D y las habilidades de SAGA|Equivalencia de habilidades entre AD&D y SAGA]].
#''Códigos de las Habilidades'': existe una [[tabla propuesta por el sistema SAGA|Códigos de habilidades para las clases de Dragonlance AD&D]].
[>img[Arte de William Teo en www.dlnexus.com|http://www.dlnexus.com/gfx/art/10366.jpg]]
*[[1er Paso]]: Tomar cartas de creación de personaje
*[[2do Paso]]: Elegir Naturaleza y Comportamiento
*[[3er Paso]]: Determinar cantidad de Aventuras, Tamaño de Mano, y Reputación
*[[4to Paso]]: Determinar Riqueza y Estatus Social
*[[5to Paso]]: Asignar cartas a cada Habilidad
*[[6to Paso]]: Determinar Código de cada Habilidad
*[[7mo Paso]]: Escoger Escuelas de Hechicería y/o Esferas de Misticismo
*[[8vo Paso]]: Calcular puntos de magia
*[[9no Paso]]: Escoger Raza
*[[10mo Paso]]: Escoger Rol
*[[11vo Paso]]: Escoger Equipo
Una alternativa para los jugadores veteranos de Dragonlance, cuando se utilizaba el sistema [[Advanced Dungeons & Dragons]], es no crear un personaje nuevo, sino [[convertir un personaje viejo al sistema SAGA|Convertir estadísticas de AD&D a SAGA]].
//True Believer//
|!Valores de Habilidades|!Códigos de Habilidades| !Otros Requerimientos|!Ventajas|!Desventajas|
|Espíritu 4 min|Espíritu B min (para sacerdotes) o D min (para seguidores)|Debe seleccionar un dios a seguir|Bono de +3 para acciones de Presencia ante otros creyentes; Bono de [[Carta de Triunfo]] para cualquier acción, una vez por aventura; Puede adoptar el rol durante el juego|Penalización entre -1 y -6 para acciones de presencia con aquellos que no comparten sus creencias|
En vez de atacar, puede "cubrir" a su objetivo con un arma de misil. El héroe hace el chequeo de ataque pero no dispara. Si tiene éxito, en cualquier intercambio posterior a ese instante puede pegar automáticamente. Tomar acciones mientras se cubre al objetivo cancela la acción.
Healer
Ability Scores Ability Codes Other Req.’s Advantages Disadvantages
Any. St “B” max. None. Trump to healing actions. No trump bonus for
Dx “B” max. attacks meant to injure;
Re “C” min. difficult to acquire role
Pe “C” min. during play.
Citadel Healer
Before Chaos War, Goldmoon was a priestess of Mishakal, goddess of healing. It is therefore only natural that the Citadel of Light should produce a fair number of mystics who specialize in the healing arts. One of Goldmoon´s greatest desires is to keep the spirit of the Gods of Good alive on Krynn, and none contribute more to this goal than Citadel Healers.
Role Playing:
Citadel healers, in some ways, embody the ideal that priests of Mishakal once sought to attain. Thet are selflessly devoted to alleviating pain and suffering among the people of Ansalon. Downtrodden peasants and proud knights, poor refugees and despotic warlords –all may receive the benefit of their healing magic. Some healers charge for their service or perform their miracles in exchange for room and board, but they never charge an excessive amount. (A hero who would charge a lord five steel pieces for healing his daughter might ask from a poor peasant only a dry corner in wich to sleep for the same service).
Without fail, Citadel healers are soft-spoken, gentle men and women. They try to avoid violence and defuse conflict whenever possible, but they also understand harsh reality well enough to know that sometimes violence is indeed the only answer. They always push for the solution that promises the least harm –and then only after exploring all avenues for negotiation with foes.
Requirements:
Citadel healers must have at least a “B” code in Spirit, as well as acces to the healing sphere. (Heroes with “A” codes may select any other two additional spheres allowed for Citadel mystics).
Like other mystics of the fellowship, healers must have at least a Spirit score of 4. They are not interested in combat; therefore, they have Strength and Dexterity codes of “C” or lower and Agility and Endurance codes of “B” or lower. Finally, they must have attained a reputation of Adventurer to have progressed beyond aspirant level.
Advantages:
Large parts of a Citadel healer´s training are devoted to the study of the physiology of Ansalon´s various intelligent races, as well as the use of salves, medicinal herbs and nonmagical healing methods. For this reason, these heroes always receive a trump bonus for treating injuries, wounds, and diseases in humans and humanoids or offering them first aid.
Additionaly, Citadel healers can correctly diagnose illnesses or poisoning cases and identify poisons with a successful Reason action, whose difficulty is determined by the Narrator. (A mishap leads to misdiagnosis.)
Heroes can adopt this role during play, although it requires a period of additional training for a mystic to learn the skills of a healing specialists.
Disadvantages:
The primary disadvantage of Citadel healers is that they are not exceptionally skilled in the arts of war –they spend too much time healing injuries to learn how to cause them effectively. Therefore, they never receive a trump bonus for nonmystical attack actions.
Cada habilidad tiene un código que determina cuán entrenado o talentosa es una persona en las pericias asociadas a cada [[Habilidad]]. Los niveles de familiaridad con las pericias se miden como sigue:
|!Código|!Familiaridad|
|A|Completa|
|B|Alta|
|C|Promedio|
|D|Restringida|
|X|Nula|
Abajo se interpreta el significado del código para cada habilidad:
|!Habilidades|!Pinta|!Significado|!A|!B|!C|!D|!X|
|>|>|>|>|>|>|>|bgcolor(#a0ffa0):''Físicas'' - De Coordinación|
|!Agilidad|Escudos|Saber usar Escudos|Cualquiera|Todos, menos los Muy Pesados|Muy Ligeros, Ligeros, o Medianos|Ligeros o Muy Ligeros|Sólo los Muy Ligeros|
|!Destreza|Flechas|Saber usar armas de misil|Cualquiera|Todas, menos las Muy Pesadas|Muy Ligeras, Ligeras, o Medianas|Ligeras o Muy Ligeras|Sólo los Muy Ligeras|
|>|>|>|>|>|>|>|bgcolor(#a0ffa0):''Físicas'' - De Fortaleza Física|
|!Resistencia|Yelmos|Saber usar Armaduras|Cualquiera|Todas, menos las Muy Pesadas|Muy Ligeras, Ligeras, o Medianas|Ligeras o Muy Ligeras|Sólo las Muy Ligeras|
|!Fuerza|Espadas|Saber usar armas de cuerpo-a-cuerpo|Cualquiera|Todas, menos las Muy Pesadas|Muy Ligeras, Ligeras, o Medianas|Ligeras o Muy Ligeras|Sólo los Muy Ligeras|
|>|>|>|>|>|>|>|bgcolor(#a0ffa0):''Mentales'' - Intelectuales|
|!Razonamiento|Lunas|Saber [[Hechicería]]|Usar máximo 3 [[Escuelas]]|Usar máximo 1 [[Escuela|Escuelas]]|Muy conocedor - No puede usarla|Conocimiento superficial - No puede usarla|Desinformado sobre el uso y teoría, puede experimentar fobias o fascinación|
|!Percepción|Orbes|Sentidos Agudos/Deficientes|Dos Agudos|Uno Agudo|Todos Normales|Uno Deficiente|Dos Deficientes|
|>|>|>|>|>|>|>|bgcolor(#a0ffa0):''Mentales'' - Esenciales|
|!Espíritu|Corazones|Saber [[Misticismo]]|Usar máximo 3 [[Esferas]]|Usar máximo 1 [[Esfera|Esferas]]|Muy conocedor - No puede usarla|Conocimiento superficial - No puede usarla|Desinformado sobre el uso y teoría, puede experimentar fobias o fascinación|
|!Presencia|Coronas|Liderazgo|Excelente - Coordina 25 personas|Bueno - Coordina grupo de 10|Promedio - Coordina grupo de 5|Ligero - Coordina su actividad con otra persona|Ninguno|
|![[Luchadores|Heroes de Acero]]|!Clase|!Agilidad|!Destreza|!Resistencia|!Fuerza|!Razonamiento|!Percepción|!Espíritu|!Presencia|!Escuela/Esfera|
|~|![[Bárbaro]]|C|A|C|A|D|A|C|C|N/A|
|~|![[Soldado de Caballería]]/[[Caballero (Knight)]]|A|A|A|A|C|C|C|A|N/A|
|~|![[Guerrero]]|A|A|A|A|D|C|C|B|N/A|
|~|![[Marinero]]|B|B|B|B|D|B|C|C|N/A|
|~|![[Paladín]]|A|A|A|A|C|C|B|B|Curación/Sensitividad|
|~|![[Montaraz]]|A|A|A|A|C|B|B|C|Animismo|
|![[Magos|Heroes de la Hechicería]]|!Clase|!Agilidad|!Destreza|!Resistencia|!Fuerza|!Razonamiento|!Percepción|!Espíritu|!Presencia|!Escuela/Esfera|
|~|![[Alta Hechicería|Mago de Alta Hechicería]]|X|X|X|X|A|A|C|D|Escuelas según la [[túnica|Órdenes de Alta Hechicería]]|
|~|![[Renegado|Mago Renegado]]|X|X|X|X|A|A|C|D|3 Escuelas|
|![[Clerigos|Heroes de Corazón]]|!Clase|!Agilidad|!Destreza|!Resistencia|!Fuerza|!Razonamiento|!Percepción|!Espíritu|!Presencia|!Escuela/Esfera|
|~|![[Paganos|Clérigo Pagano]]|A|C|A|A|C|C|A|C|3 Esferas|
|~|![[Órdenes Sagradas|Clérigo de la Sagrada Orden de las Estrellas]]|A|C|A|A|C|C|A|C|Según la [[orden clerical|Sagradas Órdenes de las Estrellas]]|
|![[Bribones|Heroes Vagabundos]]|!Clase|!Agilidad|!Destreza|!Resistencia|!Fuerza|!Razonamiento|!Percepción|!Espíritu|!Presencia|!Escuela/Esfera|
|~|![[Bardo]]|C|C|C|C|C|B|C|B|N/A|
|~|![[Estafador]]|C|C|C|C|C|B|C|B|N/A|
|~|![[Apropiador]]|C|C|C|C|C|A|C|C|N/A|
|~|![[Ladrón]]|C|C|C|C|C|B|C|C|N/A|
Esta tabla puede servir como guía. Sin embargo, es importante recalcar que resulta evidente que está superficialmente construída a partir de las definiciones del //Players Handbook//, y el significado de los códigos en cada habilidad no traduce esas definiciones de forma exacta. Por ejemplo, un Caballero, según el //Player's Handbook// puede utilizar arco, por ser un tipo de luchador. Sin embargo, en Dragonlance los [[Caballeros de Solamnia]] desdeñan el uso de armas de misil, por lo que probablemente podrían no haber entrenado en esa arma.
De igual forma, un Montaraz, al ser un guerrero, en principio podría utilizar una armadura completa de placas, sin embargo, muchas de sus habilidades dependen de que no use armaduras pesadas. Por ende, un Montaraz podría no haber entrenado en ese tipo de armadura.
Finalmente, un Clérigo no tiene habilidades en D&D 2da Edición, que impliquen afectar grandes cantidades de personas, o dar órdenes. Sin embargo podría tener código A en Presencia por ser un líder religioso.
[[Inicio]]
[[Agradecimientos]]
Con una acción de dificultad retadora de Destreza (resistida por Fuerza) un Héroe puede intentar golpear el arma del oponente obligándolo a soltarla.
Cuando una acción es fallada luego de utilizar una carta dragón, o habiendo sido la última de las cartas, una de dragón, el fallo no es normal. Es una [[desgracia|Desgracia]].
En general:
*Fácil - dificultad 4 (cualquier mortal puede intentarlo y con frecuencia tener éxito)
*Promedio - dificultad 8 (sólo los héroes tienen éxito frecuentemente)
*Retadora - dificultad 12 (un héroe se preocupa)
*Desalentadora - dificultad 16 (un héroe, difícilmente lo logra)
*Desesperada - dificultad 20 (sólo ante desesperación, un héroe lo intenta)
*Imposible - dificultad 24 (eso... imposible, es la materia prima de las leyendas)
Es un número que indica la complejidad de un hechizo. La dificultad total de un hechizo es la suma de las dificultades de [[Tiempo de Invocación de un Hechizo]], [[Rango de un Hechizo]], [[Duración de un Hechizo]], [[Área de Efecto de un Hechizo]], y la [[Intensidad de Efecto de un Hechizo]].
Adicionalmente, hay modificadores sobre la dificultad según el contexto del hechizo, como por ejemplo:
*si el hechizo es [[resistido]], se suma el número que tenga la víctima en la habilidad correspondiente a la defensa mágica.
*si el hechizo no es realizado en calma, sino en una situación incómoda o estresante, puede haber modificadores de dificultad.
*si el hechizo es totalmente nuevo (improvisado), tiene una dificultad adicional. Esto se subsana con la práctica y la elaboración de un método de conjuración, o con ayuda de otros hechiceros, investigación en una biblioteca, etc.
La Dificultad Total es un número que debe ser sobrepasado con el valor numérico de la acción del jugador, sumando las cartas utilizadas (incluyendo las de bono de [[Carta de Triunfo]]) y la habilidad mágica pertinente (Espíritu en el caso de Misticismo, y Razonamiento en el caso de la Hechicería). También debe ser superado por el número de [[Puntos de Magia]] asignados al hechizo.
|>|!I - [[Invocación]]|>|!II - [[Rango|Rango de un Hechizo]]|>|!III - [[Duración|Duración de un Hechizo]] |
|[[Tiempo de Invocación|Tiempo de Invocación de un Hechizo]]|[[Dificultad|Dificultad de un Hechizo]]|[[Rango de un Hechizo]]|[[Dificultad|Dificultad de un Hechizo]]|[[Duración de un Hechizo]]|[[Dificultad|Dificultad de un Hechizo]]|
|30 minutos| 1 |Personal| 1 | Instantáneo | 1 |
|20 minutos| 2 |Combate Cuerpo-a-cuerpo | 2 | 1 minuto | 2 |
|10 minutos| 3 |Distancia de "tiro de piedra" | 3| 15 minutos | 3 |
|1 minuto| 4 |Misil Lejano | 4 | 30 minutos | 4 |
|Instantáneo| 5 | Artillería |5 | 1 hora |5 |
|-|-|-|-|1 día| 6 |
|-|-|-|-|1 semana| 7 |
|-|-|-|-|1 mes| 8 |
|-|-|-|-|1 año| 9 |
|>|>|>|>|>|!IV - [[Área]] |
|''IV.a - Personas'' | ''Dificultad'' | ''IV.b - Espacial''| ''Dificultad'' | ''IV.c - Tiempo'' | ''Dificultad'' |
|Indivíduo | 1 | Indivíduo | 1 | 1 minuto | 1 |
|Pareja | 2 | Cuarto Pequeño| 2| 1 hora | 2 |
|Grupo Pequeño (5) | 3 | Cuarto Grande| 3| 1 día | 3 |
|Grupo Grande (10) | 4 | Casa Pequeña| 4| 1 semana | 4 |
|Multitud (25) | 5 | Casa Grande| 5 | 1 mes | 5 |
|-|-|-|-|1 año| 6 |
|-|-|-|-|10 años| 7 |
|-|-|-|-|100 años| 8 |
|-|-|-|-|1000 años| 9 |
|>|>|>|>|>|!V - Efecto |
|''V.a - Daño''|''Dificultad'' |''V.b - Curación'' |''Dificultad'' |V.c - Inusual |''Dificultad'' |
|+/-1 a 2 | 1 | 1 carta/punto | 1 |Irritate (+/-1) | 1 |
|+/-3 a 5 | 2 | 2 carta/punto | 2 | Problemático (+/-2) | 2 |
|+/-6 a 9 | 3 | 3 carta/punto | 3 |Estorboso (+/-3) | 3 |
|+/-10 a 14 | 4 | 4 carta/punto | 4 | Impedimento (+/-4) | 4 |
|+/-15 a 20 | 5 | 5 carta/punto | 5 | Doloroso (+/-5) | 5 |
Con una acción de Agilidad de dificultad promedio, resistida por Razonamiento, puede intentar escapar del efecto de cubrimiento, o hacer que su oponente pierda el próximo turno.
!Creando un Draconiano
#Si al elegir las cartas de tu [[Mano del Destino]] sacas tres o más cartas dragón, puedes decidir hacer un personaje draconiano. En caso de desear hacerlo, debes colocar a un lado las cartas dragón, y sacar un número adicional de cartas idéntico al número de cartas dragón que tenías inicialmente. Si sacas más cartas dragón al hacer esto, colócalas a un lado también, y continúa hasta tener doce cartas del destino, que tengan las pintas normales
#Manteniendo las cartas dragón a un lado, construye el personaje noramlmente, con las 12 cartas escogidas en el paso 1.
#Debes decidir si estás haciendo un Bozak o un Sivak.
##__Bozak:__ Si estás haciendo un Bozak, resta un total de 5 códigos de Agilidad, Destreza, Resistencia y Fuerza, y añade un número igual a la suma de los valores de las cartas dragón a los atributos mentales (Presencia, Espíritu, Percepción y Razonamiento). Asegúrate de que el código de Razonamiento es A.
##__Sivak:__ Si estás haciendo un Sivak, resta un total de 5 códigos de Razonamiento, Percepción, Espíritu y Presencia, y añade un número igual a la suma de los valores de las cartas dragón a los atributos físicos (Agilidad, Destreza, Resistencia y Fuerza). Asegúrate de que el código de Fuerza es A, y el máximo código de Razonamiento y Espíritu es C.
##En cualquier caso, ninguna habilidad debe tener un valor mayor a 15. Si sobran puntos, deben ser ignorados.
!Ventajas
*Debido a sus gruesas escamas y su innata resistencia mágica, cualquier carta jugada para recibir daño, es una carta de triunfo.
*Al subir sus habilidades debido a la experiencia, se suben las habilidades en las que perdieron códigos en el momento de creación.
*Cuando se intente subir una habilidad de las que fueron mejoradas usando las cartas dragón, debe hacerse de la siguiente forma:
##Si la carta levantada es dragón, se considera carta de triunfo.
##Si el nuevo total es más alto que su actual valor, y la pinta de la carta coincide con la habilidad en cuestión, esta subirá.
##Para subir un código en una habilidad mejorada con las cartas dragón, debe sacarse el 10 de dragones y luego el 9 de la pinta correspondiente a la habilidad que desea subirse.
Cualquier comentario respecto a este sistema propuesto por [[James Lai|mailto:synicism1@worldnet.att.net]], les recomiendo hacerlo directamente a él, con copia a mi, en idioma inglés.
!Ejemplo de Draconiano generado con este sistema
|!Nombre|Kavin|
|!Raza:|Draconiano (Sivak)|
|!Rol:|//Jaded Veteran//|
|!Aventuras:|8|
|!Riquesa:|3|
|!Lugar de Origen:|Sanction|
|!Agilidad:|12B|
|!Razonamiento:|4C|
|!Destreza:|12A|
|!Percepción:|7B|
|!Resistencia:|12A|
|!Espíritu:|6C|
|!Fuerza:|14A|
|!Presencia:|8A|
|!Habilidades Especiales:|Vuelo alado|
|!|Vista aguda|
The Druid:
In former ages, people used to call "Druids" both Nature deities priests or heathen priests, false gods' believers or druids from other AD&D worlds. Now, while the power of the heart is been spread through all Ansalon, thanks to the Citadel of Light and other enlightened hearts, the druids are back to Ansalon, fighting for nature and living in peace in Krynn's forests. Druids dress in a very distinctive way, looking very rustic in their brown or green robes. They usually have long beards (men) or hair (women). They are men and women that live apart from the world, using their gifts in Balance's sake.
A Druid is, actually, a mystic gifted with Animism and/or Alteration. Just a handful mystics from the Citadel of Light choose to follow the druid way, therefore many druids discovered their abilities by chance. A Druid is a calm, attentive and healthy person, so he/she must have at least 6 in Spirit, Perception and Endurance. It is required some special abilities to be a druid - good senses and inner peace are carved in a druid soul, so his/her codes must reflect this, having at least B in Perception and Spirit. Druids have very good health, but they can't either wear heavy armor, or wield any Sorcery school, so C is their maximum ability code in Endurance and Reason. A druid must have Animism or Alteration Spheres, while the other Spheres are chosen by the player. Dwarves, Elves, Half-elves, Humans and Kender can be Druids, but humans, elves and half-elves are more suited for this role.
A druid receives trump bonus while using Animism or Alteration Spheres, in actions with animals or searching for rare herbs or vegetables. It counts as Herbalist skill, in case of Skills usage featured in "A Saga Companion". It reflects, in game terms, druid affinities with nature.
On the other hand, druids can never get trump bonuses for Necromancy or Spiritualism Spheres, because they are connected to life itself, and these Spheres reflect death aspects. Druids never receive trump bonus while trying Presence actions in the city, or with those not accustomed with natural environments. They are also responsible by all living things near their havens - all plants and animals should receive attention and protection. Druids living near desolated regions, as Malys' Desolation or Gellidus' domains, must fight the Great Dragons and try to restore the former natural balance.
Es el tiempo por el que se mantiene activo un hechizo. En la quinta era es virtualmente imposible realizar un conjunro de efectos permanentes.
En el caso de las transmutaciones, la finalización del hechizo devuelve al objeto afectado la composición física original, mas no la forma.
Ejemplo: Si una espada de acero fue convertida en mercurio, desparramándose en el piso comportándose como un líquido, al terminar el hechizo, cada gota de mercurio derramada se convierte en una esfera de acero, o en un trozo de acero en la forma que había tomado el mercurio.
Las acciones simples siempre son exitosas, siempre y cuando no sea ejecutada con algún tipo de riesgo o apremio. Cuando haya razones para pensar que la acción podría fallar, debe seguirse los siguientes pasos:
!1. Declaración
El jugador anuncia lo que intentará hacer su héroe. También puede ocurrir que el Narrador informe al jugador que debe intentar la acción. Ejemplo típico: "Por favor haz un chequeo de percepción".
!2. Determinar Habilidad de la Acción
El Narrador debe decidir qué habilidad es la relevante para que el héroe intente la acción. Cada habilidad está asociada con una [[pinta|Pinta de las cartas]] de las [[Cartas del Destino]]. Ambos, [[la habilidad y la "pinta" están asociadas a cierto tipo de acciones|Lectura de las cartas]].
!3. Determinar Dificultad de la Acción
El Narrador estima cuán difícil es la acción, en términos de un valor de [[dificultad|Dificultad de Acciones]].
!4. Jugar una carta
El jugador elige una carta de su mano, y la coloca sobre la mesa. Si la [[pinta|Pinta de las cartas]] de la carta está asociada a la habilidad que se está usando para la acción (ejemplo: una carta de corazones para una acción de Espíritu), la carta se considera [[Carta de Triunfo]], y por ende el jugador levanta una carta del Mazo del Destino, y la coloca sobre la mesa, al lado de la que jugó previamente, sumándose los valores de las cartas para efectos de calcular el valor de la acción.
Independientemente de si la carta fue de Triunfo o no, una vez es jugada una carta, el jugador debe tomar una nueva del mazo para mantener constante el número de cartas en ella.
!5. Resultado
El jugador añade el valor de su habilidad al valor de la carta (o cartas) jugada(s). Se aplican los bonos correspondientes a la pericia utilizada, en caso de que aplique, o correspondiente a alguna ventaja por rol, por raza o individual. El valor resultante debe ser superior a la dificultad para que la acción sea exitosa. La dificultad total de la acción incluye, si la acción es con oposición, la habilidad correspondiente del oponente, y las penalizaciones de desventajas por rol, raza o individuales que apliquen.
Si la dificultad total excede al valor obtenido por el jugador al lanzar su carta del destino, y esta última es de la [[pinta|Pinta de las cartas]] de los dragones, entonces el fallo es catastrófico, pintoresco, o caótico. Este tipo de resultado se denomina [[desgracia|Desgracia]].
Ejemplo: Roselenna, una elfa Qualinesti, está tratando de saltar un precipicio. El Narrador decide que la habilidad de la acción es Fuerza, y que por la distancia la acción es Retadora (teniendo entonces una dificultad base de 12). Sin embargo, Roselenna sufre de fobia leve a las alturas, aumentando la dificultad en 4 puntos, para un total de 16. El jugador de Roselenna decide utilizar el 10 de Dragones, y lo añade a su Agilidad que es 7, generando una acción de 17 puntos. Como el valor de la acción es mayor a la dificultad, Roselenna logra saltar al otro lado del precipicio.
!!Acciones Opuestas o Resistidas:
Cuando un héroe enfrenta resistencia, el paso 5 cambia: a la dificultad se añade la habilidad con que el oponente resiste la acción. Ejemplo: Roselenna dispara con su arco para herir a un ogro. Todo ataque con armas de misil utiliza la habilidad Destreza, y el esquivar es una acción de Agilidad. Roselenna utiliza el 5 de Espadas, y suma a ese valor su Destreza, que es 9, para un total de 14. Debido a la distancia el Narrador considera que la dificultad base es Promedio (8), y debe sumar a la dificultad la Agilidad del ogro, que es 5, para un total de 13. La flecha hiere al ogro.
|!Weapon|!Class|!Dmg|!Att.bonus|!Special|
|Buckler|VL|-|1|puede ser lanzado a rango "misil cercano"|
|Kite|L|+1|2|puede ser lanzado a rango "misil cercano"|
|Target Shield|M|+2|3|-|
|Horse Shield|H|+3|4|-|
|Tower Wheild|VH|+4|5|-|
|!Símbolo/[[Pinta|Pinta de las cartas]]|!Habilidad|!Tipo de acción|!Color/[[Aura|Aura de una carta]]|!Significado del Código Asociado|
|!Escudos|Agilidad|Acrobacias / esquivar / equilibrio|Verde|Entrenamiento para utilizar escudos|
|!Flechas|Destreza|Coordinación ojo mano / manipulación fina / combate con armas de misil|Turquesa|Entrenamiento para utilizar armas de misil|
|!Yelmos|Resistencia|Resistencia / Inmunidad a enfermedades / defensa en combate cuerpo a cuerpo|Azul|Entrenamiento para utilizar armaduras|
|!Espadas|Fuerza|Fuerza Bruta / ataque en combates cuerpo a cuerpo|Púrpura|Entrenamiento para utilizar armas de combate cuerpo a cuerpo|
|!Lunas|Razonamiento|tareas intelectuales / memoria / hechicería|Marrón|Entrenamiento en Hechicería|
|!Orbes|Percepción|Percepción / Intuición / resistir magia de hechicería|Café|Cantidad de sentidos agudos o deficientes|
|!Corazones|Espíritu|Fuerza de Voluntad / magia mística / Fuerza emocional / Empatía|Naranja|Entrenamiento en Misticismo|
|!Coronas|Presencia|Liderazgo / Autoestima / resistencia a magia mística|Dorado|Capacidad de liderizar grupos de personas|
|!Dragones|Desgracias|Eventos inesperados o peligrosos|Blanco,Rojo o Negro|Entrenamiento completamente nulo en una habilidad. Fobia. Fascinación.|
Son elfos con una conexiòn innata con sus bosques natales, y desde muy temprana edad muestran afinidad y una inexplicable intuición acerca de animales y plantas. Esta conexión es independiente de la antígua magia clerical, de la Alta Hechicería, e incluso del misticismo y hechicería de la [[Era de los Mortales]]. Cada pueblo élfico tiene un enfoque distinto, y una denominación diferente para referirse a los Moldeadores de Madera:
|!Subraza|!Kalanesti|!Silvanesti|!Qualinesti|
|!Nombre|Shamanes de la Madera|Casa de los Moldeadores de Madera|Moldeadores del Destino|
|!Enfoque|"Moldeador" es un término inadecuado para ellos, pues desean armonizar más que controlar a la madera. Ven a los empeñados en la civilización, como una corrupción de lo "élfico". Se consideran bendecidos por los dioses, y la mayoría son aprendices de shaman. La mayoría murió en la guerra contra el dragón blanco [[Gelidus]], defendiendo sus tierras. La mayor parte de los sobrevivientes se han unido a su gente en la isla de [[Cristyne]] donde cuidan a la próxima generación de Shamanes de la Madera. Por primera vez, consideran la posibilidad de usar sus poderes para otra cosa que estar en comunión con lan aturaleza|El sistema de castas de los Silvanesti ha confinado a los Moldeadores de Madera a la "Casa de los Moldeadores de Madera. Nunca se casan con elfos de otra casta para garantizar que la descendencia preserve los poderes (son hereditarios). En la [[4ta Era]] podían unirse a la la orden de Solinari, de Alta Hechicería, o a la Órden Sagrada del Árbol de la Vida, un culto druídico menor de los Silvanesti, dedicado a servir a la diosa [[Chislev]]y a su consorte [[Zivilyn]]. Eran responsables de mantener la belleza del Bosque de Silvanesti, y mantener en buen estado las defensas vegetales del reino. Luego de la [[Guerra de la Lanza]] era una de las castas más respetadas, pues fue una de las protagonsitas en la erradicación de la [[Pesadilla de Lorac]] que corrompió al bosque durante la guerra. Algunos afirman que el misterioso escudo protector que aisla al bosque en la [[Era de los Mortales]] fue creado por miembros de esta casta. |En Qualinesti, estos elfos no son forzados a seguir ningún camino de vida. Usualmente comparten el gusto de sus primos Silvanesti de moldear el bosque con fines de ordenamiento, esteticos, y utilitarios. Ser un Moldeador del Destino, es ser un elfo élite. Gracias a elos los cultivos, parques y bordes protectores del bosque se mantienen en excelente forma. No tienen la creencia de tener un destino asignado por los dioses. Sin embargo, algunos consideran que [[Chislev]] los ha tocado y que, en algún momento, harán algo que tendrá un gran efecto en los hechos del mundo. Algunos, en la [[4ta Era]] se convirtieron en [[Clérigos]] de [[Chislev]]. Algunos se han unido a la [[Ciudadela de la Luz]] para expandir sus poderes, con la ayuda del [[Misticismo]]|
|!Personalidad|Creen que comparten el espíritu con un árbol en particular de su tierra natal (en la mayor parte de los casos, [[Ergoth del Sur]]. Usan su poder para curar a los árboles y plantas, y defender el bosque de quienes lo destruyen o intentan expandir la civilización a través de ellos. Típicamente, opinan que sus primos moldeadores de madera han pervertido su don. Los más radicales, consideran que moldear un árbol según los propios deseos es tan malo como destruírlo. Suelen ser solitarios, con pasiones muy profundas, pero lentos en caer en la ira. Sólo la destrucción voluntaria de la naturaleza hará que uno de estos elfos se enfurezca realmente. La mayoría son pacifistas.|Se consideran elegidos de los dioses para una misión sagrada. Moldear lo salvaje y descontrolado del ambiente, en formas funcionales y ordenadas, representan el triunfo del Orden sobre el Caos, y por lo tanto la manifestación de la divinidad. Casi todos fueron [[Clérigos]]. Están entre los más arrogantes y racialmente intolerantes de los elfos Silvanesti. Una y otra vez, han visto sus esfuerzos para moldear el Bosque Silvanesti en un paraíso, deshechos por invasores y seres de otras razas. Sienten un particular odio por los [[Kalanesti]] y los [[Medio-elfos]]. En el mejor de los casos, opinan que los [[Kalanesti]] desperdician su talento. En cuanto a los [[Medio-elfos]], los ven como manifestaciones de Caos. Los Dioses del Bien jamás quisieron que criaturas como esas existieran. Son abominaciones de la naturaleza, y por lo tanto, con seguridad, inherentemente destructivas.|Son más sociables que los [[Kalanesti]], y se relacionan de forma productiva con otras razas, incluso aunque mantengan un rastro de prejuicio en contra de los matrimonios inter-raciales. Están entre los más patrióticos, y muchos forman parte de los movimientos de resistencia liderizados por [[Gilthas]] y [[Laurana]], y por [[Porthios]] y [[Alhana Starbreeze]]. Están ofendidos por el bosque innatural que ha creado el Gran Dragón [[Beryl]] dentro y alrededor de Qualinesti. Muchos se han unido a las filas de la [[Ciudadela de la Luz]]. Allí enseñan a otros Qualinesti, y apoyan tanto a la [[Ciudadela de la Luz]] como a los movimientos de resistencia élfica, garantizando excedentes en los cultivos, para aprovisionarlos.|
Además de cumplir con los requerimientos, ventajas y desventajas inherentes a la raza, deben cumplir con lo siguiente:
|!Valores de Habilidades|!Códigos de Habilidades|!Otros Requerimientos|!Ventajas|!Desventajas|
|Espíritu 5 min|Ninguno|Ninguno|Nunca ocurre una [[Desgracia]] cuando realizan hechizos de las escuelas de [[Aeromancia]], [[Geomancia]], [[Hidromancia]], o [[Piromancia]], ni de la esfera de [[Animismo]]. Las [[desgracias|Desgracia]] son simples fallos. Nunca se pierden las habilidades innatas, y pueden adoptar otros roles, manteniéndo las ventajas de un Moldeador de Madera.|No pueden aprender las escuelas de [[Encantamiento]], [[Conjuración]], ni [[Transmutación]], ni las esferas de [[Mentalismo]] o [[Necromancia]]. Nunca pierden las desventajas del rol. Pueden escoger el rol, sólo al momento de la creación del héroe.|
!Notas Adicionales
*Los [[Kalanesti]] deben además cumplir con los requerimientos, ventajas y desventajas, de un [[Shamán Kagonesti]].
*Para los Silvanesti, es importante considerar lo que se menciona en [[The Sylvan Veil|http://www.amazon.com/SYLVAN-VEIL-Advanced-Dungeons-Dragons/dp/0786913290]] (El Velo Silvestre): los elfos de esta casta, aunque tienen muchas habilidades en común con la Casa de Jardineros, su don no está compuesto de intuición y sabiduría ancestral familiar, sino de los espíritus de la naturaleza. Los de más alta casta, vivierno en una construcción hecha de árboles entrelazados. Desde allí, dirigían el trabajo de los moldeadores de menor rango, que vivían y trabajaban en el bosque. Trabajan duro para expandir y restaurar las defensas que aíslan el bosque del mundo exterior.
[>img[Arte de Nick Barfuss en www.dlnexus.com|http://www.dlnexus.com/gfx/art/14079.jpg]]
(Silvanesti y Qualinesti)
!Requerimientos
*Valor mínimo de 6 en Agilidad (Agi), Destreza (Dex), Presencia (Pre).
*Valor máximo de 8 en Resistencia (End), Fuerza (Str)
*Código B mínimo en Destreza (Dex) y Fuerza (Str).
*Código C máximo en Agilidad (Agi) y Resistencia (End).
!Ventajas
*[[Carta de Triunfo]] en combates con espadas y usando percepción en bosques.
!Desventajas
*No hay [[Carta de Triunfo]] nunca en acciones de presencia (Pre) con no-elfos (excepto para resistir misticismo)
[>img[Imagen de PsychaDurmont en www.dlnexus.com|http://www.dlnexus.com/gfx/art/18924.jpg]]
Las dos razas de elfos acuáticos existentes en Ansalon son:
*Dargonesti, cuya estructura social y personalidad es similar a los [[Silvanesti]], y se convierten en delfines.
*Dimernesti, cuya estructura social y personalidad es similar a los [[Qualinesti]], y se convierten en focas.
Fueron creados por accidente debido a los efectos mágicos de la Piedra Gris (//Greystone//).
Suelen tener un estilo de lucha basado en red y tridente.
!Descripción
Lucen como elfos con piel de colores azulados y cabello verdoso, azulado o incluso rubio. Es frecuente el cabello plateado entre los Dimernesti, sin embargo. Los ojos son de color verde o azul.
La piel brilla con pequeñas escamas, y poseen membranas entre los dedos de los pies y las manos. Llevan prendas ligeras, confeccionadas a partir de algas y plantas marinas, excepto cuando salen del agua. En esas ocasiones prefieren llevar túnicas o capas con capucha que oculten su piel.
!Requerimientos
*Valor Mínimo de 6 en Agilidad (Agi), Destreza (Dex).
*Valor Máximo de 8 en Fuerza (Str), y Resistencia (End).
*Código Máximo de "C" en Destreza (Dex), Resistencia (End), Agilidad (Agi) y Fuerza (Str).
*Código Mínimo "B" en Percepción (Per). Poseen vista aguda y sentido "marino".
*Código Mínimo "B" en Espíritu (Spi), con la escuela de Alteración.
!Ventajas
*[[Carta de Triunfo]] en el uso de red y tridente en el combate.
*[[Carta de Triunfo]] en acciones de percepción y razonamiento en ambiente acuático.
*Todo elfo acuático puede transformarse o en foca o en delfín, usando una carta del triunfo.
!Desventajas
*Tiempo máximo de permanencia fuera del agua de 2 horas por cada punto de Resistencia (End). El elfo, cumplido el plazo, debe hacer un roleo de Resistencia (End) cada hora. Si pierde, se reduce en un punto en todas las habilidades, hasta que regrese al agua de mar. Si hay un Mishap, pierde dos puntos en cada habilidad. Si se reduce a cero (0), pierde la consciencia y muere en una hora.
!Combate con red y tridente
El héroe hace un ataque normal e intenta atrapar al enemigo (éste no debe ser mayor que un delfín). La acción es de Destreza (Dex) contra la Agilidad (Agi) del oponente, y a una dificultad de 8 puntos. Si acierta, el oponente no se puede defender. Todos los ajustes por armadura aplican, pero no los de escudos. El enemigo debe gastar el próximo turno saliendo de la red, lo cuál requiere un roleo de Agilidad (Agi) de 8 puntos de dificultad.
[>img[Arte de JeiWo en DeviantArt.com|http://th05.deviantart.net/fs42/300W/f/2009/146/c/8/Wild_Elf_by_JeiWo.jpg]]Kalanesti es la palabra usada en los libros en español, en sustitución de //Kagonesti//, el término originalmente utilizado en inglés.
!Requerimientos
*Valor mínimo de 6 en Agilidad, Destreza, Percepción y Presencia.
*Valor mínimo de 5 en Espíritu.
*Valor máximo de 7 en Razonamiento.
*Código máximo de D en Agilidad y Resistencia
*Código mínimo de B en Destreza y Percepción
*Código máximo de B en Fuerza
*Código mínimo de D en Espíritu
!Ventajas
*Bono de [[Carta de Triunfo]] para ataques con arco recto o recurvado
*Cada día pueden encantar una flecha por cada carta en la Mano del Destino, como un item de renombre (+4 al daño y al ataque), si está en su tierra natal.
*Bono de [[Carta de Triunfo]] para acciones de Percepción, moverse en silencio o esconderse en bosques.
!Desventajas
*No pueden utilizar armas, ballestas ni armaduras con metal forjado.
*No pueden usar [[Carta de Triunfo]] para acciones de Presencia con otras razas (excepto para resistir misticismo).
*Penalización de -3 en acciones de Presencia con Silvanestis, y -2 con Qualinestis.
*Prohibidas las escuelas de magia de:
**Criomancia
**Electromancia
**Espectramancia
**Transmutación
*Prohibidas las escuelas de misticismo de:
**Necromancia
**Espiritualismo
Ambassador
Ability Scores Ability Codes Other Req.’s Advantages Disadvantages
Any. Pr “C” min. Demeanor from Trump for negotiation; No trump for Re or Pr
Red aura card; action to discern thoughts; actions to deal with
wealth 7 min. can adopt role during play. lower classes.
The trickster is a person who lives by his wits. Smooth talking, quick-thinking and flashy, the trickster uses weapons as a last resort, since his natural talents usually allow him to get in and out of trouble without a fight.
!Role Playing:
Tricksters can be role-played in a number of different ways. At heart, however, all tricksters love adventure and love to work a crowd. Some end up being con-artists, others end up to be true showmen, and still others work as part-time pickpockets.
!Requirements:
Tricksters need to be prepared for all sorts of different situations. This being the case, tricksters must have a score of at least 5 in Agility, Dexterity, Endurance, Strength, Reason, Perception and Spirit. All tricksters love to be at the center of attention (as long as the crowd isn't entirely composed of the city guard) and to work crowds, so they must have a minimum score of 7 in Presence. Since wit and show are a trickster's most important characteristics, his Reason and Presence scores have no limit, but unfortunately, every other ability score is limited to a maximum of 7. Furthermore, no trickster can ever be a sorcerer, and so an ability code of X is required for his Reason score. A trickster can have an ability code of up to B in Spirit, but he must choose Alteration as his mystical sphere if he does. All other abilities are limited to a maximum code of C.
Civilized humans, half-elves and kender can be tricksters. Tricksters may not start out with a wealth score higher than 4, but if he pulls any "scams" during the game that prove to be fruitful, this score can be raised.
!Requirements:
|Stats|Score|Code|
|Agility| Between 5 and 7 |C max|
|Dexterity| Between 5 and 7 |C max|
|Endurance| Between 5 and 7 |C max|
|Strength| Between 5 and 7 |C max|
|Reason| 5 min| Only X|
|Perception| Between 5 and 7 |C max|
|Spirit| Between 5 and 7 |B max (only alteration)|
|Presence |7 min| C max|
|Quests |Max 4 at start |-|
!Advantages:
Whenever trying to smooth-talk, hustle, charm, entertain a crowd, or perform a similar Presence action, tricksters enjoy an automatic trump bonus. This does not apply if the other party is hostile towards the trickster.
Tricksters can also use their talents to work the opposite way. Whenever trying to start a brawl, insult or enrage people, tricksters receive the same bonus.
Every trickster has a specialty with some common item, such as a deck of cards, a set of bean bags, a handkerchief, and so on (not a weapon). A trickster can do all sorts of tricks and sleight-of-hand stunts with this item, and so receives an automatic trump bonus whenever using it. Furthermore, this bonus does not just apply to the one deck of cards or one set of jacks that the trickster has always had, but to any similar deck or set. The Narrator should use some discretion with this bonus. For example, if the trickster attempts to sever the red dragon Malystryx's head with a playing card, the Narrator should not allow the bonus.
A hero cannot acquire the trickster role during play.
!Disadvantages:
Tricksters rely heavily upon luck in their everyday lives. Consequently, every trickster carries around a token of luck, like a rabbit's foot or a lucky coin. If a trickster discovers that his token is missing, he can never receive any trump bonuses, all of his actions must be random draws, and he suffers a -3 penalty on all action scores until he gets the token back. If this token is actually destroyed, he must abandon this role. If he finds a new lucky token (on a quest) while still without a role, he may re-adopt the role of Trickster immediately without penalty. It is up to the Narrator to decide whether or not the lucky token actually grants the hero any real bonuses.
All races, including Dwarven, who know of Battle Rage have a high respect (or even fear) of it's effect. Due to the insane rage that the Dwarf can whip up, they will throw thenselves into any battle at any chance. -Hence the name 'Battle Rager'. Increasing their enemies (and friends) uncomfortableness, is the fact that they have wear constantly squeaking metal armour and have an gruff attitude which they surround themselves with. -Made worse by the presence of Non-Dwarven races. If he respects the king/leader then they will always do their best for the group.
!Role Playing:
The Battle Rager's Score Requirements:
| Ability |scores | Codes |
| Str |7 min| B min |
| End |8 min | C min |
| Agl |6 min | C min |
| Re |6 max |X max |
| Pe |7 max | D max |
| Spr |----- | C max |
''Other Requirements:''
The role is restricted to Dwarfs only with-in the acceptable scores and codes. They can only reach a max wealth of 5.
!Advantages:
Trump bonus's for the melee weapons: sword, hammer and axe. Also for breaking down doors and other such destruction. As well as this, the Dwarf may enter battle rage every 2.5 hours, gaining +3 to Endurance, +1 to Strength and defense adjustment of -2.
!Disadvantages:
There are no trumps for agility while in the Battle rage. If hindered during a rage, then he will attack no matter who it is and must pass an average perception action to stop that attack. Upon exiting the rage (lasting max 45 mins) he loses 3 from normal Strength score and 1 from normal Endurance score. After the period he must take an challenging Endurance check to return to normal scores. If he fails, he may try again 10 minutes later, And so on...
[>img[Imágen propiedad intelectual de Wizards Of The Coast|http://www.edu.physics.uoc.gr/~lookas/pictures/lance56.jpg]]
(de las Colinas, y de las Montañas)
!Requerimientos
*Valor máximo de 8 en Agilidad (Agi) y Destreza (Dex)
*Valor mínimo de 6 en Resistencia (End) y Fuerza (Str)
*Máximo código de B en Razonamiento (Rea)
!Ventajas
*Siempre cuenta con Carta de Triunfo para resistir venenos y [[Hechicería]]
!Desventajas
*Jamás disfrutará de Carta de Triunfo para ciertas acciones de personalidad.
!Descripción
Estas criaturas fueron creadas mágicamente a partir de un humano, incorporando la esencia del dragón azul Skye. Llegan a medir poco más de siete pies, y pesar alrededor de 300 libras. Tienen cuerpos humanoides con piel azul y cubierta de escamas. Tienen alas, hocicos con grandes dientes, y garras en pies y manos. Fueron los primeros engendros de dragon creados en Krynn.
!Requerimientos
*Mínimo código A en Agilidad y Destreza debido a que pueden volar.
*Valor mínimo de 8 en Agilidad y Destreza.
*Deben tener un valor de 7 y un código B mínimo en Fuerza debido a ser extremadamente fuertes.
*Deben tener un código mínimo de A en Resistencia debido a las gruesas escamas que cubren su cuerpo.
*El código de Razonamiento sólo puede ser igual a B.
*El valor de Razonamiento no puede ser mayor a 5.
*Mínimo un valor de 7 y un código de A en Percepción.
*Máximo valor de 5 y código X en Espíritu.
*Código máximo de X en Presencia.
*La riquesa no debe ser mayor a 2.
*Empiezan al menos con 4 aventuras.
!Ventajas
*El check para volar es automáticamente considerado una carta de triunfo.
*Los checks para cualquier acción de Fuerza o Resistencia son siempre cartas de triunfo.
*Se considera que poseen la Escuela de Magia de Electromancia, debido a que pueden disparar rayos desde su boca hacia sus enemigos.
!Desventajas
*No pueden utilizar la electricidad como ataque sino una vez por día.
*Cualquier acción de Presencia que no sea de tipo intimidatoria tiene una penalización de -8.
|!Habilidad en SAGA|!Cálculo en base a Habilidades de AD&D|
|Fuerza|Fuerza / 2|
|Resistencia|Constitución / 2|
|Agilidad|Destreza / 2|
|Destreza|Destreza / 2|
|Razonamiento|Inteligencia / 2|
|Percepción|Sabiduría / 2|
|Espíritu|Sabiduría / 2|
|Presencia|Carisma / 2|
Siempre los redondeos son hacia arriba.
[>img[Arte de Ksar en www.dlnexus.com|http://www.dlnexus.com/gfx/art/12371.jpg]]
La Guerra de Caos fue narrada en El Ocaso de los Dragones, y significó el cambio de la faz de Krynn. Los Dioses "se fueron", llevándose con ellos la magia, dando orígen a una nueva era, la Era de los Mortales o Quinta Era.
Ha habido varias novelas narrando los hechos de esta Era de los Mortales. Pronto colocaré acá una lista con la [[bibliografía]] pertinente.
Entre los cambios más importantes ocurridos en Krynn, está el hecho de que, tal y como cuando el gato se va, los ratones hacen fiesta, al irse los Dioses, su lugar fue tomado por los Señores Dragón.
La historia de DragonLance ha avanzado, tanto en novelas, como en publicaciones basadas en Calabozos y Dragones, en lo que se llamó la Guerra de las Almas. Sin embargo este sitio está dedicado casi exclusivamente a la Era de los Mortales.
!Cambios en la Nueva Era
[[La Nueva Magia]]
[[La Nueva Caballería]]
[[Los Enanos|Los Enanos en la Era de los Mortales]]
[[Los Elfos|Los Elfos en la Era de los Mortales]]
[[Los Draconianos|Los Draconianos en la Era de los Mortales]]
[[Los Kenders|Los Kenders en la Era de los Mortales]]
[[Los Gnomos|Los Gnomos en la Era de los Mortales]]
[[La Nación Goblin de Throt]]
[[Palanthas|Palanthas en la Era de los Mortales]]
[[Puerto Balifor]]
[[Knightlund]]
[[Solace]]
Este artículo y sus secciones son traducción y paráfrasis de lo escrito por Juddog. Gracias a él por su aporte!
Una acción promedio de Fuerza o Agilidad opuesta por Fuerza, permitirá escapar de situaciones de llaves, agarres y sometimiento.
!Aeromancia
Todo lo que tiene que ver con el aire y el clima
!Criomancia
Magia del hielo
!Adivinación
Tener conocimiento de los alrededores, o de lugares distantes. Vision del pasado, y visiones vagas, borrosas y cambiables del futuro.
!Electromancia
Todo lo que tiene que ver con la electricidad y el magnetismo
!Encantamiento
Mágicamente cambiar las propiedades de un objeto, sustancia o material.
!Geomancia
Todo lo que tiene que ver con polvo, tierra, piedras, metales, etc.
!Hidromancia
Todo lo que tiene que ver con el agua.
!Piromancia
Lo que tenga que ver con el fuego.
!Espectromancia
Lo que tenga que ver con la luz y las ilusiones visuales.
!Conjuración
Habilidad para teletransportarse. Si se usa en combo con otras escuelas, permite Conjurar criaturas y personas.
!Transmutación
Capacidad de cambiar la composición de un objeto. Si tiene código "A" en Razonamiento, puede cambiar el objeto en cualquier cosa asociada a sus otras escuelas mágicas, temporalmente. Si es "B", sólo puede cambiar su composición a algo similar a lo que ya es. Sin embargo, esta esfera se vuelve realmente importante al ser combinada con otras escuelas y esferas.
!Animismo
Habilidad de sentir, comunicarse con, y controlar cualquier ser viviente no-inteligente (no funciona el control en criaturas de Razonamiento 3 o más)
!Alteración
La habilidad para transformarse a sí mismo o a otros físicamente. Cuando se realiza, las habilidades físicas deben ser cambiadas para reflejar la nueva forma. La suma de todas las habilidades físicas del ente afectado debe ser redistribuída a criterio del narrador. Por cada punto de diferencia respecto a la suma original, la dificultad del hechizo aumenta en uno (ya sea una diferencia positiva o negativa). El nuevo tamaño de la criatura es aproximadamente el mismo que el original, a menos que haya ajustes importantes a la dificultad según juicio del Narrador. Un Héroe con Código "A" en Espíritu puede tomar la forma específica de una criatura en particular (una cierta persona, un cierto animal), mientras que un héroe con código "B" puede sólo tomar la forma básica general.
!Canalización
Es la capacidad de alterar los valores de las habilidades físicas del místico o de otro ente. Modificar cada habilidad requiere de un hechizo por separado.
!Curación
Es la habilidad de curar mágicamente heridas y enfermedades.
!Meditación
Es igual que la Canalización, sólo que para las habilidades mentales. Si los valores de Razonamiento y Espíritu son alterados, los puntos de magia siguen siendo los mismos.
!Mentalismo
Es la capacidad de comunicarse telepáticamente y/o controlar la voluntad de una criatura. Incluye efectos sugestivos y alucinaciones. Héroes con código de espíritu de "A" pueden cambiar memorias, inducir alucinaciones, y subjugar voluntades. Aquellos con código "B" sólo pueden realizar comunicación telepática
!Necromancia
Trata con la energía vital y la manipulación negativa de ésta. No puede devolver vida a un compañero caído. Puede afectar sólo el cuerpo del ente muerto, creando un muerto-viviente. Trata de la animación anti-natural de cuerpos muertos. No por ello la criatura muerto-viviente creada carece necesariamente de consciencia, pues ésta no tiene su camino natural, sino que puede quedar encerrada en el cuerpo animado mágicamente.
!Sensitividad
Funciona como la escuela de hechicería de Adivinación, pero en lo referente a las criaturas y sus sentimientos, alma, emociones, intenciones, en vez de referirse al ambiente y los hechos acontecidos. Un héroe con código de Espíritu "A" puede sentir las emociones de un héroe o criatura en un determinado lugar, si éste pasó por allí en el pasado, aunque ya no esté. Un héroe con código "B" puede sólo sentir entes cercanos.
!Espiritualismo
Es igual que la Necromancia, pero trata con los espíritus. Va desde la simple detección, hasta la comunicación y control de la voluntad de un espíritu. Un héroe con código "A" puede conjurar criaturas espirituales o héroes del reino de los muertos. Héroes con código "B" sólo pueden controlar muertos vivientes etéreos y comunicarse con espíritus.
Certain individuals are gifted with the ability to offer convincing theatrical performances, to lead the masses, or to make profound arguments on the strength of their personality alone. Some such folk become entertainers or politicians, using their skills at least partially to benefit others. On the other hand, some choose to use their talents for purely selfish means. These individ-uals become con artists.
Con artists make their living by creating scams, playing sleight-of-hand tricks, and preying on the superstitions of the ignorant. These tricksters devote themselves to swindling up a fortune, copper by copper. Sorcerers dislike their phony magic tricks, mystics take offense at their false spiritual claims, healers resent their fake salves, war-riors distrust their underhanded ways, and thieves hate them for using their Con games to steal from them. Tika Waylan Majere's father, Alleran Waylan, was a con artist who targeted only rich lords.
!Role-playing:
Happy-go-lucky sorts at heart most con artists' view the world in the context of what they can squeeze out of it. A rare few focus their efforts only on those who can afford to lose their money, such as lords in their opulent palaces, but most five little or no thought to whom they con. Of course, these con artists stand at the top of their fields and often spend hundreds of steel pieces to plan a heist that will net them thousands of steel pieces. These elite can pick and choose their targets at leisure. As con artist heroes represent the cream of the crop, most of them are too big to take a peasant's last copper.
A discussion of staging cons appears in Chapter Two.
!Requirements:
Con artists must have a Presence code of "B" or better to seem trustworthy while running their cons. Additionally, they cannot have a nature drawn from a card with a white aura. Even the most conscientious con artist, one who tar-gets only other blackguards, isn't that sensitive toward others.
!Advantages:
Heroes with this role have a way of making others feel at ease, easily earning their trust. Con artists enjoy a trump bonus to any Presence action they attempt to convince a mark they really are selling bottled dragon breath or whatever their con of the day. (This benefit cancels out racial dis-advantages regarding Presence actions.)
Inspired heroes can acquire the role of a con artist during play.
!Disadvantages:
Once characters discover what the con artist does for a living, they will find it hard to trust him again-this may apply to other heroes, too. 'When dealing with characters wise to his games, the con artist receives no trump bonus for Presence actions. (Races that nor-mally do not receive a trump bonus to Presence actions involving other races instead suffer a -3 action penalty for such actions.)
Of all the places to study magic in Ansalon, the Academy of Sorcery is surely the most prestigious. One could not hope for a more inspirational environment than the Academy, founded by Palin Majere and located just south of Solace. Academy Students have access to one of the most complete collocations of sorcerous knowledge on Krynn (for details on the ACademy of Sorcery, see chapter three in this book or page 86 in Dusk or Dawn from the FIFTH AGE boxed set).
Those who are serious about learning sorcery, and have the aptitude to be accepted, can find no better place to study than the Academy of Sorcery. Being a student is a challenging enterprise, however. Everyone at the Academy is considered a student -even the founder, Palin Majere himself- and everyone is expected to devote himself to his studies and consistently add to the pool of knowledge. Only those who are serious about sorcery as a way of life should consider enrolling in the Academy. It is too demanding a lifestyle to be entered into without absolute resolution.
Emma Xela, described in Chapter Five, is one Academy student.
* Role-playing
Academy students are very serious about sorcery -some might say too serious. They have devoted their lives to plumbing the depths of this new type of magic, experimenting with the application of sorcery (improving effects and durations), casting spells using two or more different schools of sorcery, and even attempting to combine sorcerous spells with mystical ones. Many people feel that the students at the Academy are too involved with their studies and don´t spend enough time interacting with people outside their field. Although this is not universally true, Academy students do tend to think of sorcery and the study of magic in general as more important than most other, more mundane topics.
Life at the Academy is not easy. Practically every minute of the day is filled with practicing, researching, or teaching sorcery. To help students avoud being consumed by their lessons, the Academy has a plicy which requires them to spend at least six weeks of the year away from the Academy itself. Despite his push for them to lead more complete lives, most students remain fixated on their studies and use the time away to engage in outside research or, if they are more daring, go on adventures and quests to put their theories to practical tests. The stereotypical Academy student may "have his nose buried in his spellbook", but student heroes can be of any temperament and academic inclination. They simply must live with the fact that being associated with the Academy will cause many folks, particularly those in Solace, to make various assumptions about them; mostly others think them aloof and somewhat disconnected from "things that really matter".
Heroes choosing this role are not required to be of what is generally considered "school age". Because sorcery is a new art which many of the old practitioners of High Sorcery are trying to master, and because everyone associated with the Academy is considererd a student regardless of age or ability, this role can be used for a hero of any background and can be maintained as a role throughout a hero´s entire career.
Note:
There are two variant roles based on the Academy student. First is the aspirant Academy student -one who wishes to enter the Academy but, for some reason, has not been accepted. Perhaps he does not yet meet the requirements for entrance, or perhaps a political problem keeps him out; this should be a Narrator-controlled plot device pitting the hero against some aspect of the Academy bureaucracy and should be the focus for a series of adventures which culminate either in the hero´s acceptance to the Academy or a change in his life goals.
The other variant is the former Academy student. This is a hero who, at one point in his life, studied at the Academy of Sorcery, but has since left. There are any number of reasons for leaving the school, but this hero left in such a way that he is no loner welcome at the Academy (details are left to the player and Narrator to decide). Former Academy students have the same requirements as Academy students, but the advantages and disadvantages of independent sorcerers (see page 14).
* Requirements
The academy will accpet as students those of any race who demonstrate sorcerous ability. To become an Academy student a hero must have a Reason score of at least 4 and a code of at least "B". Those with lower scores simply do not possess what the Academy considers the minimum intellect to understand the nature of sorcery. Those with lower codes are aspirants. They are not considered Academy sorcerers until they improve their understanding of sorcery (represented by increasing their Reason code to at least a "B").
* Advantages
There are many benefits to be gained from enrollment at the Academy of Sorcery, not the least of which is the resources of the school itself. The Academy Governing Council allocates the school´s discretionary funds to projects deemed to be of superior merit. If a hero/student needs money, manpower, or other support for an adventure which may provide useful information or material for the Academy, he need only make a formal request for support from the Governing Council. This request is a challenging Presence action, but the difficulty may be modified by the attitude of the council, reputation of the petitioner, current events, or other factors the Narrator deems appropiate. Should the request be accepted, the Academy will lend whatever aid and support it can afford, based on the significance and urgency of the project.
Academy students also have the advantage of always having experienced colleagues to consult before casting difficult spells. Since the Academy is home to one of the largest collections of sorcerous knowledge on Krynn, it can serve as a superb source of aid for research and study. A hero/student can increase his chances of success at any spell if he first seeks out the advice of his mentor or a sorcerer who specializes in the school of magic he is working with. Such advice will gain the hero a +1 bonus to his spell action. Alternatively, if the spell the hero plans to cast is too dangerous or difficult, the narrator can choose to have the sorcerer character advise the hero against the attempt (telling the player that the action is doomed to failure).
Heroes can enroll in the Academy during play.
* Disadvantages:
There are many responsanbilities associated with being an Academy student, not the least of which are the obligations to add to the reservoir of knowledge the school represents and to help in the education of less skilled students. For every week they spend in residence at the Academy of Sorcery, students must spend at least ten hours teaching less advanced students, and at least fifteen hours doing research or participating in experiments in one of the shools in which they have proficiency. Furthermore, they are required to write detailed accounts of the results of all research and demonstrate any successful spell innovations before a Council of Peers.
A less acknowledged drawback to being an Academy student is that the school and its residents are significantly removed from the day-to-day problems of Ansalon. The Academy itself, located on a plateau overlooking but separated from the town of Solace, is like a world of its own. While the students go into town on a regular basis for entertainment, food and supplies, they are not considered part of the local population. This physical isolation, when combined with the skittishness many folks feel around magic users, can cause students from the Academy to become somewhat detached and even uninterested in significant events of the day. Because of this "disconnectedness", many normal folk find it difficult to relax around or indeed even to trust the students. As a result, hero/students may never gain the benefit of trump cards during Presence actions with characters who (in the Narrator´s estimation) are not used to dealing with sorcerers or other academic types. (This disadvantage does not apply to actions made to resist mysticism.)
Una acción retadora de Agilidad opuesta por Fuerza o Destreza, puede permitir al jugador evitar todos los ataques contra él. Si falla, la cantidad por la que falla es añadida al daño base que provoca el ataque.
Cuando se transita camino desconocido o peligroso, se requiere de una persona que esté adelante, reconociendo el terreno. Es, a menos que se diga lo contrario, el que tenga mayor percepción.
[>img[Arte por Lindsay Archer en www.dlnexus.com|http://www.dlnexus.com/gfx/art/20604.jpg]]
Perhaps the least understood figures in the Legion of Steel are the Legionnaire scouts. Folks say that in the wilderness these heroes' expert woodsmen and trackers can be found only when they wish it. However, they feel equally at home in urban settings. They can skulk in the shadows like murderous cutthroats or pass themselves off as mer-chants or locals with little effort.
These scouts serve as the eyes and ears of the Legion of Steel. Before the Order prepares an assault or establishes a pres-ence in a new town, its scouts arrive on the scene. They skillfully note weak spots in an enemy's defenses, determine a local commander's or lord's secret advisers, and identify potential sources of support and recruits. They might pose as Knights of Takhisis or some equally unsavory types in an effort to become intimately familiar with an enemy organization. These scouts face the challenge of making friends among the Legion's enemies, learning as much as possible about their plans, and then betraying them.
!Role-playing:
Generally, Legionnaire scouts are with-drawn and private people. They don't make true friends easily because they tend to distrust other, those who regularly betray people find it hard to shake the feeling that someone's going to do the same to them. As long as the scout keeps everyone at arm's length, however, the betrayal will never come.
!Requirements:
Needless to say, a hero must belong to the Legion of Steel in order to play this role. The Legion requires its members to have a demeanor and nature drawn from cards with values of 6 or less. In addition, a scout cannot derive his nature from a card with a white aura.
As a full Legionnaire, a scout must have a reputation of Adventurer or above (less experienced Legionnaires are still in training). He should not have a wealth score beyond 5, as the Legion's goals do not involve amassing personal riches.
The scout must have scores of 3 or better in all his abilities, and a Perception code of no less than "B." Because this hero would rather skulk in the back-ground than serve as a leader, he needs a Presence code of "C" at maximum.
!Advantages:
Every card played by a Legion-naire scout trying to conceal himself in an urban or forest setting is auto-matically considered trump. Addition-ally, the scout always enjoys a trump bonus to track an animal or an individual in natural sur-roundings.
The scout, more adept than most heroes at adopting facades, can acquire any false role he chooses, disregarding the normal limi-tations mentioned in the "False Roles" section on page 29.
Like all Legionnaires, the scout must train an apprentice: a character of Unknown reputation with scores and codes each 1 point or rating below the hero's own. These character essentially a second hero for the player assists the scout in his Legion missions as part of his training until he becomes a Novice.
Heroes with the proper background may acquire this role during play.
!Disadvantages:
The slightly paranoid air about a Legionnaire scout makes him a less-than-inspirational leader. Thus, he may never gain a trump bonus for Presence actions that involve leadership attempts.
Having an apprentice has its draw-backs as well as its good points. The scout must support the apprentice out of his own wealth and is responsible for turning him into a fully trained Legionnaire. 'While he might not want to take the apprentice with him on the most dangerous undercover missions, he mustn't neglect him, either. 'When the Narrator deems the hero's overprotection is hindering his apprentice's training, the player must attempt an average Presence (Presence) action, opposed by the apprentice character, to prevent the youngster from quitting the Legion. Failure at the action means the scout's player must immedi-ately turn over the top card of the Fate Deck and reduce his hero's Presence score by one-third the value of the card (rounded up), to represent his loss of face in the organi-zation. Drawing a Dragons card means the hero loses a category of reputation as well. The Legionnaire scout faces the same random draw if he lets his apprentice die in the line of duty. A disadvantage of all Legionnaires is that their great rivals, the Knights of Takhisis, usually execute any members of the Legion they capture.
Desolation Scout:
It is needed more than only luck to survive the harsh environments of the Desolation. Kender and humans alike learned that lesson as their lands were corrupted by Malystryx in the dawn of the Age of Mortals. Now, living in a place which the closest comparation would be the Abyss, the wandering tribes of kender and humans rely on their scouts to keep them alive.
A Desolation Scout is a man or woman trained in the arts of finding water and safe shelter in the arid lands, how to treat the most common diseases in the area, the beasts that inhabit the terrain and how to destroy them. They have high endurance to the hard conditions of the land and they are capable experts in survival tactics.
To be a Desolation Scout, a hero must have an Endurance and Perception value of 6 or higher, and Agility must be at least 8. The maximum code allowed in Endurance is C, and a Perception code of B is also necessary. The Desolation requires agility to overcome obstacles, and armors are a setback in such warm and mountainous environment. Keeping an eye open for every detail is also important, and that is why a high Perception is important.
Desolation Scouts receive a Trump bonus for any card played in actions to follow tracks and survival actions in the Desolation, such as looking for safe shelter, food and water. Tests to identify animal tracks and poisonous plants are also always trump for Desolation Scouts. However, Desolation Scouts are very afraid of dragons and their fearsome powers, because they have seen the terrible things Malys caused to their homeland: no card played while resisting Dragonawe is ever Trump. Desolation Scouts also were raised to resist the heat of the Desolation and therefore they are very vulnerable to cold weather: no card played in cold environments or even in temperate winters is Trump for Desolation Scouts. This can be a problem in places like the Icewall or even during Solace's mild winter.
/***
|Name:|ExtentTagButtonPlugin|
|Description:|Adds a New tiddler button in the tag drop down|
|Version:|3.2 ($Rev: 3861 $)|
|Date:|$Date: 2008-03-08 10:53:09 +1000 (Sat, 08 Mar 2008) $|
|Source:|http://mptw.tiddlyspot.com/#ExtendTagButtonPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License|http://mptw.tiddlyspot.com/#TheBSDLicense|
***/
//{{{
window.onClickTag_mptw_orig = window.onClickTag;
window.onClickTag = function(e) {
window.onClickTag_mptw_orig.apply(this,arguments);
var tag = this.getAttribute("tag");
var title = this.getAttribute("tiddler");
// Thanks Saq, you're a genius :)
var popup = Popup.stack[Popup.stack.length-1].popup;
createTiddlyElement(createTiddlyElement(popup,"li",null,"listBreak"),"div");
wikify("<<newTiddler label:'New tiddler' tag:'"+tag+"'>>",createTiddlyElement(popup,"li"));
return false;
}
//}}}
The Loyal Servant
A hero with the 'loyal servant" role works in the household of a high-ranking or wealthy enemy, so he can watch his foe's plans develop. More often than not, employers trust this hero implicitly, even if he is secretly a prime source of information for those who oppose them.
Although the hero might not know how to use a sword properly, he leads a life more dangerous than most front-line soldiers. Not only does he risk being discovered as a traitor, but the loyal front he presents may make him a target for those who would hurt his master. Anyone who courts opposition from both the villains and those loyal to his own cause is truly playing a dan-gerous game.
Role-playing:
The "loyal servant" always seems friendly toward his master, as well as the family and any visitors to the house. Eager to please them, he always tries to stay one step ahead of their needs. This is only a facade, though. His friendliness gets him close to the action, and his desire to remain one step ahead of those he serves makes him appear indispensable.
Further, if a hero with this role is ever caught eavesdropping, or perhaps tailing a villain who recently visited his master, he has a fair chance of bluffing his way out of a potentially bad situa-tion. Characters are prone to believe even a mildly convincing story that comes from their faithful servant.
Note: Because a "loyal servant" becomes familiar with virtually every detail of his master's life, the Narrator has an opportunity to give a vrnain a sympathetic side. For example, an oppressive, corrupt lord may be enact-ing his foul plots to protect his wife and child, whom he loves very much-he may even be a very gentle and loving parent. Another employer might beat his wife, torture prisoners routinely, and force his young son to perform weapon practices until the boy drops from exhaustion. In both examples, the vil-lain may see his "loyal servant" as an assistant and a confidant. Each situation generates dilemmas that can create interesting role-playing situations.
Requirements:
It takes mental stamina to seem friendly toward, supportive of, and subservient to that one actually opposes (and perhaps even despises), so heroes with this role must have Spirit and Reason scores of at least 4.
Advantages:
Heroes who act as servants become adept at eavesdropping, as well as lis-tening for approaching footfalls while searching through documents on the master's desk. Any cards played for such surreptitious actions are consid-ered trump.
A hero can acquire this role during play, however he must have had some prior acquaintance with his employer to establish the bond of trust.
Disadvantages:
Beyond his immediate circle of secret allies outside his master's household, a "loyal servant" hero has difficulty con-vincing those who share his true sym-pathies that he is on their side. Whenever trying to deal with "good guy" characters, the hero must perform an average Reason (Spirit) action, opposed by the leader of those he seeks to convince of his true intentions. Mishaps might involve the hero being dismissed, imprisoned, or even attacked, depending on the situation.
The Outlaw Role
Role-Playing
These Heroes don't like the "LAW"... They can't accept any types of authority... Usually, they are wanted by the authorities. Though, to be an outlaw doesn't always mean to be bad. You can be a kind of Robin Hood or something similar. You are only an outlaw at the authority's eyes. Of course, there are bandits and highwaymen who love to rob people or do similar crimes.
Requirements
Outlaws are excluded from society and the civilization. They must live in the woods or with their own community but always besides civilization. Thus, they require a minimum of 6 for Endurance and Spirit. The Social Status must be between Slave and Commoner. They can use every weapons but they like missile-types to strike from a safe distance.
Advantages
They have a safe place to live, a hideaway, usually in a forest, a distant valley or the city's sewer system. The Narator should decide about that place.
Disadvantages
Outlaws tend to be lightly equiped for running, hiding and act quickly. Also, authorities are looking for him... as well as bounty hunters and others...
[>img[Imágen de autoría desconocida|http://img690.imageshack.us/img690/1960/gnolllgnoll.jpg]]
!Descripción
Los Gnolls fueron creados por la Gema Gris junto a otras criaturas "hostiles e inhumanas" como los goblins y los minotauros. Habitan en las llanuras de Ansalon en jaurías nómadas, de forma no muy distinta a los bárbaros de las llanuras. En general funcionan con mentalidad de jauría/manada, y usan la fuerza de los números para pelear. Son fieros y competitivos. Tienden a estar aislados, cuando están alrededor de las otras razas de Krynn, pero se sabe de algunos que han formado lazos con algunos miembros de otras razas. Ellos mentiran, robarán, harán trampas y halagarán a cambio de favores, pero tienen "honor de batalla". A pesar de no ser tan inteligentes como otras razas, lo compensan en ferocidad.
Orvago, un gnoll, ha ayudado a Goldmoon en sus esfuerzos para fundar la Ciudadela de la Luz.
Lucen como un híbrido entre hombre y hiena. Típicamente miden entre siete y ocho pies de alto, con ojos que varían en tonalidades entre marrón y negro. Caminan sobre dos patas y sus manos tienen garras, aunque pueden manipular objetos tan bien como cualquier humano. Normalmente visten taparrabos y adornos tribales.
!Roleplay
Tienden a ser extremadamente agresivos y aparentemente barbáricos. Aunque sus maneras lucen simples y toscas, son enemigos ingeniosos y mortales. Muchos muestran una tendencia hacia la cobardía y la maldad, pero, como cualquier otra raza, es capaz de honor y decencia. El mundo civilizado asusta a los gnolls a primera vista. En general, las planicies son más reconfortantes que la vida ajetreada de una ciudad.
!Requerimientos
*Mínimo de 5 en todas las habilidades físicas.
*Máximo de Razonamiento 6.
*Máximo código C en cualquiera de las habilidades físicas, excepto una. Esa que se escoja, será de un código máximo de B.
*Máximo de Razonamiento y Espíritu B. En contadas ocasiones, se ha reportado la existencia de hechiceros y shamanes entre las jaurías de gnolls.
!Ventajas
*Los gnolls destacan por su experticia como rastradores. Cualquier acción de rastreo es una carta de triunfo automática.
*Tienen muchas armas "naturales". Pueden pelear con sus garras, y dientes que hacen daño +4.
*La gruesa piel que los cubre les da una defensa de -3, mientras no usen ningún tipo de armadura adicional. Si llegaran a utilizar alguna armadura, este beneficio es anulado.
*Cuando atacan con sus garras y dientes, la carta jugada es una carta de triunfo.
!Desventajas
*Debido a su fiera reputación, nunca pueden recibir carta de triunfo en acciones de presencia con las otras razas, salvo para resistir [[Misticismo]].
*Resistirse a la hechicería es un grado de dificultad mayor para los gnolls que para cualquier otro héroe.
[>img[Imágen de origen desconocido. Si conocen la autoría o propiedad intelectual, favor avisar a ozono27@gmail.com|http://2.bp.blogspot.com/_jj9y7lDF9zw/RldRhVDbYDI/AAAAAAAAAFE/dxIpGkbAnZg/s200/tinker+gnome.jpg]]
(Inventores y Pensadores)
!Requerimientos
*Mínimo de 7 en Destreza (Dex) y 6 en Razonamiento (Rea) y Percepción (Per)
*Máximo de 4 en Resistencia (End) y Fuerza (Str)
*Código máximo de C en habilidades físicas (Agi, Dex, End, Str)
!Ventajas
*Carta de Triunfo para creación y uso de grandes dispositivos, si es inventor (//tinker// o Inventor)
*Carta de Triunfo para creación y uso de pequeños dispositivos, si es pensador (//thinker// o Pensador)
!Desventajas
*Toda falla en acciones relacionadas con maquinarias y dispositivos, es una [[Desgracia]] (//Mishap//), si es un inventor
*Toda acción relacionada con maquinarias y dispositivos toma el doble del tiempo requerido, si es un pensador
Author: Steve Miller
As Heroes in the Fifth Age
By Steve Miller
In the Fifth Age boxed set, a variety of hero races were provided. While
they provided rules for all the traditional Dragonlance player character
races, they only scratched the surface of the many options available.
In an upcoming product I've written, the gully dwarves get restored to
their status as a player character race. I had also created a new player
character race--goblins.
Space reasons, however, dictated that the goblins get cut. However, unlike
the draconians, I doubt there will be another chance to print the goblin
rules, so, I decided to post it here in the newsgroup. Saga players and
Narrators can use this stuff in their personal games if they like.
Note: This is pre-edited, first-draft stuff... kinda like my posts. :)
Race Description
Goblins are short, flat-nosed humanoids with bright red skin. They stand
about 4 feet tall and weigh about 80 pounds. Their hair is usually black
or brown, although goblins with white hair are not unheard of.
Most goblins exist in tribal societies at the edges of Ansalon's
civilizations preying on the weak and unsuspecting, taking what they need
to survive through force or guile. Theirs is a nomadic existence, abused
as they by their larger cousins--bugbears and hobgoblins--and hunted by
humans, elves, and dwarves.
Goblins are found mostly in the mountains of Krynn. This is both because
the climate there suits them, and because it's one of the few places they
can live unmolested by other races. Most Ansalonians form their opinions
of goblins based on the creatures who dwell in Taman Busuk and around the
Khalkist mountains. Without a doubt, these goblins are honorless brutes
who only want to kill, eat, sleep, and pass gas. However, more civilized
goblins do exist, particularly on the island of Northern Ergoth.
Role-Playing
Through millennia of persecution--some justified, some not--goblins have
developed certain universal racial traits that help them survive.
First, goblins have no shame. They will lie, cheat, steal, flatter,
deflect blame, and suck-up in order to avoid a fight. They have long since
learned that the world operates is geared toward the survival of the
fittest, and when they're not the fittest, they just need to focus on
surviving.
But, if groveling, cheating, and lying doesn't get them anywhere, goblins
are fearsome opponents. They are vicious fighters who revel in glory and
reject cowardice when it battle. When a goblin is pressed to combat, there
is a very good reason for giving ground when he retreats.
Although each goblin tribe has its own quirks, there are two distinctly
different types of goblins that can be used as heroes, Mainland goblins
and Sikk'et Hul goblins.
Mainland goblins generally fit the stereotype of their race. They are
brutal scavengers who roam the land like a plague of bandits. They are
invariably rude, crude, and highly ignorant about anything but doing
battle. When not in battle, they are sniveling and whining and trying to
ingratiate themselves with the most powerful figure around.
Sikk'et Hul goblins have changed through their isolation on the sparsely
populated island of Northern Ergoth, and through a continued exposure to
the outgoing and friendly kender neighbors, the kender. Sikk'et Hul
goblins live in the badlands on the island's southern tip, in a fairly
orderly society, and are in the process of defining their own civilization
instead of existing on the bones of others. While they still have a love
for battle and consider it one of the highest glories, they are far less
abrasive, are open to using diplomacy in attempts to settle differences.
If mistreated, they will first attempt to resolve the situation by
convincing their abuser that he is wrong. If that doesn't work, then they
will usually attack foes who are their equal. If they don't think they can
win, they will resort to more underhanded methods, such as killing the
offender in his sleep or turning friends and allies against him somehow.
However, they never treat friends and allies in such a way unless sorely
provoked.
Requirements
The goblin race has been forged through hardship and persecution at the
fringes of Ansalon civilizations. As such, they are a hardy race, despite
their small stature. Heroes must have an Endurance score of at least 5 in
order to qualify as a goblin.
Goblins are also very agile creatures, and as such must have Agility and
Dexterity scores of 6.
Advantages
Goblins seem to have a nose for trouble and treasure. When serving as a
party's scout, goblin heroes are trump on any Perception Actions that are
related to detecting ambushes, hidden trails, and concealed or secret cave
entrances and doors.
Disadvantages
The vast majority of Ansalon's people see goblins as disgusting creatures
of Evil who are blights upon the world. As such, goblins have a difficult
time interacting with other races, both because of the way they are
treated, and the way they expect to get treated.
Goblins are never trump on socially oriented Actions when interacting with
other races (Presence and Reason Actions, most likely). The exception to
this rule are goblins from Sikk'et Hul and kender from Hylo on Northern
Ergoth. These two peoples have leaned to accept each other.
LEGAL STUFF:
Dragonlance is a registered trademark of TSR, Inc. Fifth Age and Saga are
trademarks of TSR, Inc. All characters, character names, and the distinct
likeness thereof are trademarks of TSR, Inc. Copyright TSR, Inc. 1996. All
Rights Reserved.
Steve Miller TSRSteveM@aol.com
DRAGONLANCE & RAVENLOFT Design Teams
MINE, adj. Belonging to me if I can seize and hold it.
--Ambrose Bierce, "The Devil's Dictionary"
Citadel Guardian
Not eveyone who joins the Citadel of Light is destined to become a mystic. Some, while dedicated to the cause, simply do not have the spiritual fortitude to draw forth the power within their hearts. These men and women can still serve the fellowship as guards, spies, and scorts.
Citadel Guardians stand watch over the entrances to the Citadel and patrol the forest around it. They also police the streets of Schallsea port alongside Solamnic Knights, distingished from them by they sky-blue tabards emplazonde with the Citadel´s symbol.
Daneel Warnoc is a Citadel Guardian detailed in the Prologue of A Light in the Darkness.
Role-playing:
Guardians are dedicated to protecting the Citadel and its mystics from harm. Where the mystics of the fellowship tend to look for the good in all, Guardians tend to look for the bad- and for good reason: The Citadel has many enemies. Some of these foes oppose the Order out of ignorance and fear, some because they see it as a threat to their continued power, while still others have hidden agendas to wich the Citadel mystics appear a threat. All of these opponents are prone to using violence against mystics, the Guardians know. Their role as protectors leads them to expect the worst.
Many Guardians came to the Citadel after years as warriors or cutthroats, hoping to finally escape their lives of conflict and strife. As such, some of them are slightly bitter, for they find no escape from the pervasive force of Evil, even at the Citadel. But they can see the flame of goodness burnig brightly within the members of the fellowship, and they take heart. Although many of these heroes are too disillusioned with themselves and the world to tap into the powers of the heart, they eagerly lend their expertise to protect those who can.
Other Guardians come to the Citadel in the hopes of one day entering the growing ranks if its mystics, joining its home guard as a stepping stone to that goal, or perhaps because they where unable to face their inner darkness upon the Silver Stair to become aspirants. Generally speaking, these Guardians are fairly young and far more optimistic than their battle-hardened fellows. In fact, many do manage to achieve their dreams of becoming Citadel mystics. Others even join the Guardians after having gained the talents of Citadel mystics or Masters, combining magic with the skills of a conventional warrior to carry out their duties.
The Guardians have something of a rivalry with the Solamnic Knights of Schallsea. As both groups are there to protect the efforts of Goldmoon and the other mystics, it is understandable that they constantly try to outdo each other. When conducting joint patrols, young Knights and Guardians often engage in good-natured boasting contests, and some of the more free-spirited Guardians even challenge Solamnics to friendly duels. At the same time however, it is not uncommon to see Solamnics and Guardians training together. They often form bonds of friendship and mutual respect strong enough to lead them to join each others´ personal quests.
On the other hand, the Guardians view the Knights of Takhisis with contempt. Not only are these dark paladins porpusefully Evil, they subjugate themselves to what they consider the will of the goddes Takhisis. Almost everything the Dark Knights stand for, Citadel followers oppose. There can be no friendly relations between Guardians and Dark Knights.
Requirements:
There are two kinds of Guardians: Those who stay in Schallsea to protect the island, pilgrims, and the Citadel itselfM and those who serve as bodyguards for missionaries traveling Ansalon or for mystics to a royal court.
Heroes who generally remain in Schallsea must have “B” codes or better in Dexterity, Strength, and Endurance, as well as a “C” code or better in Spirit. They engage in extensive weapons training so they may protect mystics and pilgrims from attack if need be. However, the Guardians are never the ones to initiate combat; they only react to aggression from others, wether it is directed at them or at their charges.
Guardian heroes who travel have slightly more diverse capabilities than those who keep the home fires safe. They are expected to interact with the lowest of street urchins and the most snobbish of prices. They must be every bit the diplomat but also remain on constant alert for danger and treachery. To handle this taxing job, such heroes must have scores of 5 or more in Agility, Dexterity, Strength, Perception, and Presence, in addition to the above requirements.
Those who joined the Guardians after previously serving as Citadel aspirant, mystics or Masters retain the requirements of their previous ranks wherever possible (that is, wherever these standards are not superceded by a Guardian prerequisite).
Advantages:
The Guardians have the respect of the citizens of Schallsea port and the pilgrims who come to the island. When dealing with these folk, they receive a trump bonus for all Presence actions, except those to resist mystic magic.
Additionally, traveling Guardians always enjoy an automatic trump bonus for Perception actions to detect treachery, ambushes, and the like. This reflects their wariness and dedication to the safety of their charges.
If the Narrator deems it appropiate, Guardians may retain other advantages they earned in a former mystic rank. Also, any Guardian wishing to enter the Solamnic Knighthood automatically will have their petitions heard by a knightly council, due to the respect given the Citadel.
Heroes may adopt the role of Citadel Guardian during play.
Disadvantages:
Guardians traveling with mystics can virually never let their guard down, for they know that enemies of the Citadel may strike at any moment. Knights of Takhisis in particular are a threat to mystics and Guardians alike, for even if the Citadel group travels in disguise, a Skull Knight proficient in mentalism or sensitivity may recognize the travelers for what they are.
In Schallsea, however, the Guardians have a difficult time dealing with the Wemitowuk and Qué-Nal, as the former tribe distrusts warriors and any in the latter tribe distrust the Citadel. Therefore, Guardians never enjoy a trump bonus for Presence actions involving Wemitowuk or Qué-Nal characters.
If the Guardian retains any advantages of a previous Citadel rank, he or she also retains appropiate disadvantages, as the Narrator sees fit.
[img[Arte de Nick Barfuss en www.dlnexus.com|http://www.dlnexus.com/gfx/art/19652.jpg]]
El rol del Guerrero Aventurero, corresponde a aquellos guerreros que no encuentran paz en su hogar, o trabajo. Son adictos a la aventura. Vagabundean, buscan peligros, juegan, o venden sus servicios como hombres de armas. Debe haber riesgos. Un ejemplo de este tipo de guerreros, es Caramon Majere. En los momentos en que dejó de participar en aventuras, cayó en la bebida y la depresión.
!Jugando este rol:
El guerrero aventurero es un permanente inconforme. Siempre encuentra una causa por la cuál luchar, investigar, ayudar, descubrir, conocer, curiosear. A pesar de ser de mucha valentía, también pueden ser impulsivos e inocentes tomando decisiones.
The adventurous warrior rarely seems satisfied with things the way they are. He might be content to settle down for a while, but eventually finds himself struck by wanderlust, smitten with the desire for treasure, or faced with a sudden urge to get out of town. The adventurous warrior hero might have an insatiable curiosity, a thirst for action, a personal cause, or just a knack for getting into trouble. Though courageous, such a hero is sometimes foolhardy. As centaurs and kender often admire this hero's willingness to follow his heart, this role suits these races partic-ularly well. Dwarves, on the other hand, likely consider the adventurous warrior something of a fool.
!Requirements:
An adventurous warrior depends on a finely tuned body to deal with the rigors of his errant life. Therefore, he must have an Endurance or Strength score of at least 5. In addition, either his Agility or Dex-terity score must equal 5 as well. The remaining score in each pair of related abilities must be at least 4.
An adventurous warrior has spent many years honing his physical skills. He must have an ability code of "A" in Agility, Dexterity, Endurance, or Strength. The codes for his remaining Physical abil-ities must be "C" or better.
As the adventurous warrior favors the physical over the mental and mystical, his Reason and Spirit codes can be no higher than "C."
Members of any race can play this role. However, an adventurous warrior's wealth score can never exceed 7-the hero's exploits tend to be expensive.
!Advantages:
As an experienced traveler, the adventurous warrior has developed a knack for impressing the locals wherever he goes. Any card he plays to gain information or simple favors from a character of guilds-man social Status (wealth 5) or lower becomes trump automatically. This bonus does not apply if the adventurous warrior asks the character to do something dan-gerous or criminal. The hero also can try to pass as a local wherever he goes, so long as he physically resembles the locals a human could not pass for a kender or minotaur! This feat requires a successful average Presence (Perception) action.
A hero can acquire the adventurous warrior role during play if he has aban-doned another role; he need only select a cause or quirk, as noted below.
!Disadvantages:
Every adventurous warrior follows a per-sonal cause or exhibits some behavioral pattern not related to status, power, or wealth. The hero often puts this cause ahead of other considerations. Acceptable causes and behaviors include:
1. Safeguarding or caring for a particular person, item, or place.
2. Defeating a particular villain.
3. Preserving (or defeating) a certain type of creature.
4. Locating a legendary place or item.
5. Obsessive behavior (personal cleanliness, general neatness, correct language, etc.).
6. Obscure interest (building a collection studying a lost race or civilization, sampling foods or beverages, etc.).
The hero need not bend his every effort to (promote his cause or follow his unique behavior, but he should not let an adventure pass without having it influence his actions in some way. If the Narrator feels the hero has ignored his cause or quirk too long, he can require the hero to make a challenging Reason action to avoid a per. sonal dilemma. Should the action fail, the Narrator can require the hero to respond to a problem related to his cause or quirk as appropriate to the situation.
The player and the Narrator must agree on the adventurous warrior's disadvantage before play begins. The Narrator should then create scenes that allow the quirk or cause to come into play.
Should the adventurer achieve his cause during play, or if it becomes moot (the hero actually retrieves an artifact he sought, the place he protects is destroyed etc.), the player and the Narrator must agree on a new cause. The hero need not choose it immediately, but he cannot gain in reputation until he does so: Any quest he completes without a cause is not added to his total.
A[>img[Arte de Lindsay Archer en www.dlnexus.com|http://www.dlnexus.com/gfx/art/20601.jpg]]
third great chivalric Order has arisen in the wake of the Chaos War: the Legion of Steel. The first Legionnaire warriors were Knights of Takhisis who decided that the Knighthood's dedication to solidarity at all times and persistence in all endeavors was more important than its fanatic desire to rule the world. In more recent years, the Legion has also attracted disaf-fected Knights of Solamnia-impatient with their Order's attempts at reform -and other stalwart souls with a desire to help the world through its troubles. Silver Claw, described in the Appendix of Dusk or Dawn, is a Legionnaire warrior-and High Elder of the organization.
!Role-Playing:
Governing the life of a Legionnaire war-rior is the group's motto: "All we have is each other" Members of the Legion also follow a Legacy, derived from both the Measure of the Knights of Solamnia and the Code of the Knights of Takhisis. The Legacy stresses the value of service to others, self-knowledge, personal integrity, steadfastness in the face of adversity, loyalty to those to whom loyalty is due, and justice for both the inno-cent and the guilty.
This role includes full members of the Legion as well as those who aspire to join. Though the Legion is not a covert organization, many members work undercover. Legionnaire warriors care very little for pomp and ceremony. This practical breed concerns itself more with doing the right thing than with personal honor or glory.
These warriors find themselves gener-ally respected throughout Ansalon, though non-elf Legionnaires in elf lands can still expect the cold shoulder. Mino-taurs find Legionnaires slightly more tolerable than other nonminotaurs. Many Knights of Solamnia consider members of this group independent upstarts, too undisciplined to make the grade as Knights. The Knights of Takhisis regard the Legion as an enemy organization fille with deserters and traitors. A Legionnairt captured by Dark Knights can expect a swift trial and execution-at best.
!Requirements:
A Legionnaire warrior, strong in both mind and body, has Strength and Endurance minimum scores of 6 and Dexterity and Agility minimums of 5. These heroes also must have a Presence and Perception scores of at least 5 and a Spirit score of at least 4.
Expected to be physically fit and to fight when necessary, a Legionnaire must have codes of "C" or higher in all four of his Physical abilities. In addition, he must have a code of "A" in either Strength or Dexterity. The Legion expects vigilance from its members, so this role requires a Perception code of "B" or higher.
His strenuous regimen of physical conditioning leaves a Legionnaire warrit little time for arcane studies, so his Rea-son and Spirit codes can be no better than "C" as play begins.
Only humans, dwarves, and half-elf heroes generally play the role of a Legiornaire warrior, though a member of any race might be moved to acquire it.
A Legionnaire warrior's wealth score cannot be higher than 5, as most members of this group have loftier goals than gaining wealth and often contribute excess funds to the Legion. Finally, players may not assign cards with values of higher than 6 to their hero's demeanor and nature.
!Advantages:
Widely regarded as champions of the common people, Legionnaire warriors always enjoy a trump bonus when dealing with a character of Commoner social Status or less, no matter what the hero is trying to accomplish. In a city, town, or village, a Legionnaire warrior can use his Presence score instead of his wealth rating to obtain equipment or mounts.
Members of the Legion return the enmity of other Knights. Therefore, any card these warriors play becomes trump when used to resolve any form of combat against Knights of Takhisis. In addition, they enjoy a trump bonus to any card they play for a personal or melee range attack against a Knight of Solamnia.
As an organization, the Legion concerns itself with training its members. A hero who begins play as a Legionnaire warrior with a reputation of Novice or lower becomes an appren-tice. He must undertake a series of quests to prove his worth to the Legion. Once he gains Adventurer reputation, he can apply for full membership (see page 51). Should a hero with a reputation of Adventurer or higher begin playing this role, he automatically becomes a full member.
As a full member, a Legionnaire war-rior receives the services of an apprentice with a reputation of Unknown. Players should consider an apprentice's ability scores and codes each 1 point or rating lower than the hero's. For example, if the hero has a Strength of 6A, the apprentice's Strength becomes 6B. It is entirely pos-sible that these scores will not allow the apprentice to meet this role's ability requirements. In that case, it's the hero's job to train him to make certain he does, in time.
The Narrator secretly determines the apprentice's wealth score by drawing one card from the Fate Deck. For game pur-poses, this character has an effective wealth of 1, as he depends on the hero for upkeep. The apprentice's actual wealth score merely helps determine his social status.
A Legionnaire warrior's apprentice can be of either gender or any race, provided that the character's ability scores and codes meet racial requirements. He accumulates quests just as a hero does and ends his apprenticeship when he has gained enough quests to move into the Novice reputation category (at which time he can undertake an individual quest for acceptance into the Legion). During his apprenticeship, this character remains completely under the Legionnaire warrior's control, functioning essentially as a second hero for the player. When an appren-tice has moved on, the Legion assigns the hero a new one within a month or two, at the Narrator's option.
As the Legion of Steel constantly seeks new mem-bers, a warrior-style hero can begin playing this role at any time. However, a hero with a reputation lower than Novice must apprentice him-self to an established member. Unlike an apprentice character, such a hero retains his own unique ability scores and codes, but must meet all the requirements of this role. The Narrator should provide a mentor character with a reputation higher than the hero's. Once the hero's reputation reaches Novice, he may embark on a quest to become a full Legionnaire.
Of course, a hero can become a mem-ber of the Legion without actually assuming this role (see page 50).
!Disadvantages:
As noted previously, the Knights of Takhisis usually execute any Legionnaires they capture. Although the Solamnic Knights often ally with the Legion of Steel, a great rivalry exists, nonetheless, between the rank-and-file members of the two organizations. Therefore, a Legionnaire warrior never gains a trump bonus for a Presence action involving either a Knight of Solamnia or a Knight of Takhisis.
Every Legionnaire, including warriors within the group, bears the responsibility for his apprentice's safety and well being. Should the apprentice die in the line of duty, the Legionnaire suffers great humili-ation: The hero's player must immediately draw one card from the Fate Deck, then reduce his hero's Presence score by one-third the value of the card, rounded up. Should the player draw a card from the Suit of Dragons, the hero also drops one category in reputation, as well.
In spite of this danger, the Legion expects its warriors to take their apprentices along on adventures, so they can learn what it means to be Legionnaires. Should a hero ever leave his apprentice behind while he undertakes a quest, he must attempt an average Presence (Presence) action to prevent the apprentice from quitting the Legion. Failure means the hero must immediately make a ran-dom draw, just as if the apprentice had died. Of course, a hero can send his apprentice to a place of safety during a dangerous portion of a quest. However, the Narrator should call for the Presence action mentioned above only in the most extreme cases of overprotection that could hinder the character's training.
Author: David Price (david.price@nashville.com)
Requirements
------------
Gully Dwarves are quick and nimble dispite their often short and squat
nature. Thus only heros with scores of at least 7 in Agility and
Dexterity qualify.
The legendary "stupidity" of the Gully Dwarves are somewhat accurate,
they have a maximum score of 3 in Reason and 5 in Perception.
Gully Dwarves can have an inner strength though and can have maximium
score of 6 in both Spirit and Presence.
Because of their small size, lack of training and "low" intellegent,
Gully Dwarves are limited to an ability Code of "D" in Agility, a "C" in
Dexterity, a "D" in Endurance, and a "C" in Strength. Also because of
their complete lack of understanding of sorcery they must have an
ability Code of "X" in Reason. Gully Dwarves can have an inner stength
though,they can have up to a "B" in their Spirit ability code. For
their Presence Code they can have up to an "A" with regaurd to other
Gully Dwarves, but for all other races they have a "X".
Advantages
----------
Because of their cowardly natures ,Gully Dwarves any card that is
played is allways considered a trump reguardless of its actual suit,
whenever they are running away from danger or groveling (a Perception
action) for mercy,
But when a Gully Dwarf is traped into a corner, they can attack with
great ferocity, often suprising their foes. Any card he plays to attack
the foe is automatically a trump (for personal or melee combat only).
This bonus lasts for only about 1-5 minutes. NOTE when this is used and
how long it last should be determined by the Narator, the Hero really
should be back into a corner, and not just threatend.
Do to their squalid living conditions Gully Dwarves receive an
automatic trump bonus to resist any type of decease, including
magical ones.
Disadvantages
-------------
Gully Dwarves gain no trump bonuses for personal or melee combat
(exception see above). They are perfectly happy pelting their foes from
a distance though so they can gain the trump bonus for missle attacks.
Because of their personality, apperance etc., Gully Dwarves gain no
trump bonuses for personality (Presence) actions involving other races
beside Gully Dwarves, (also except for the groveling action listed
above), and resisting Mystical spells.
Quick Reference
---------------
Ability Scores Ability Codes Advantages Disadvantage
-----------------------------------------------------------------------
AG 7 min AG "D" max Trump bonus for No trump bonus
DX 7 min DX "C" max running from for melee and
RE 3 max EN "D" max danger and personal attacks
PR 5 max ST "C" max groveling. No trump bonus
SP 6 max RE "X" Trump bonus for for certain
PR 6 max SP "B" max attack when backed personality
PR "A/X"max in a corner. actions.
Well that's all I guess, some might noticed that I did not put in the
trump bonus to resist poisons and sorcery, like the other dwarves have,
to tell the truth I couldn't decide if I should or not, I haven't had
the chance to actually test a Gully Dwarf Hero out in an actual game
session yet, so I don't know for certain what works the best.
So please fill free to make any comments or seggestions about any of the
above info, let me know what you think should I put in the trump bonus
for posions etc., or should one of the stats/codes be lower/higher,
please give reasons why though, don't just say because so.
[>img[Arte de Nick Barfuss en www.dlnexus.com|http://www.dlnexus.com/gfx/art/19653.jpg]]
Los [[Héroes|Creación de Héroes]] tienen 8 habilidades que definen lo que son y lo que pueden hacer (al menos en términos de probabilidades). Siempre hay un factor de azar que puede hacer que un personaje con gran Destreza (asociada a la puntería), falle un tiro fácil. Las habilidades son:
''Habilidades Físicas:''
*Habilidades de Coordinación:
**[[Agilidad]] (//Agility//, abreviado Agi)
**[[Destreza]] (//Dexterity//, abreviado Dex)
*Habilidades de Fortaleza Física:
**[[Resistencia]] (//Endurance//, abreviado End)
**[[Fuerza]] (//Strength//, abreviado Str)
''Habilidades Mentales''
*Habilidades Intelectuales:
**[[Razonamiento]] (//Reasoning//, abreviado Rea)
**[[Percepción]] (//Perception//, abreviado Per)
*Habilidades Esenciales:
**[[Espíritu]] (//Spirit//, abreviado Rea)
**[[Presencia]] (//Presence//, abreviado Pre)
Cada habilidad está compuesta por un valor (//score//) y un [[código|Código de Habilidades]]. El valor define el talento natural que tiene un personaje en la habilidad en cuestión, mientras que el código es una medida de cuán entrenado está en las técnicas, herramientas, pericias o profesiones (//skills//) asociadas con la habilidad. Por ejemplo, la coordinación de grupos de trabajo está asociada a la Presencia, el conocimiento teórico/práctico de la hechicería lo está al razonamiento, y el uso de armas de rango como el arco y la jabalina lo está a la Destreza.
En el caso de los héroes que utilizan algún tipo de magia, puede haber un número entre paréntesis al lado del valor y código de una habilidad, en particular en Razonamiento y Espíritu. Éste es el total de puntos de magia que posee el héroe, en caso de que este tenga la capacidad de conjurar hechizos. Según las reglas oficiales, el número es el cuadrado del valor de la habilidad (por ejemplo: si se tiene Razonamiento 6, se tienen 6x6=36 puntos de magia), pero existen [[formas alternativas|Reglas Opcionales de Magia]] de manejar esto.
Para saber qué tan fácilmente puede un héroe lograr una acción, no sólo se usan las habilidades y puntos de magia, sino que opcionalmente hay:
*[[Roles]]
*[[Razas]]
*[[Sistema Opcional de Ventajas y Desventajas]]
*[[Sistema Opcional de Pericias]]
En lo más profundo de los grandes bosques del continente de Ansalon, viven grupos de pequeñas criaturas aladas llamadas "hadas". Tienen una piel pálida, largas y puntiagudas orejas, y una delicada gracia que sugiere una posible ascendencia élfica.
Nunca verás a un hada, a menos que ella lo desee. Se pueden volver invisibles y mantenerse así por todo el tiempo que lo deseen. De cualquier manera, las hadas son una gente amistosa, y una o dos a menudo se aproximan a los visitantes, curiosas de saber que es lo que los trae al bosque.
Ellas son tienen ojos brillantes, entusiastas y son increíblemente entrometidas. De hecho, si alguna raza en Krynn es generalmente considerada más molestas que los kender, esa es la de las hadas. Se meten en todo: tus bolsos, bolsillos, e (si tu ropa no es lo suficientemente ajustada) incluso en tu ropa. Sin embargo no hacen daño.
Tienen la habilidad de sentir que alberga el corazón de una criatura, y odian pasionalmente todo aquello que haya sido incluso ligeramente tocado por la Maldad. A pesar de que son muy pequeñas y frágiles, siempre atacan a cualquier criatura malvada que conocen, tratando de sacarla de su bosque.
Destreza y Agilidad: más de 6 menos de 15 / Agi-code máx D
Fuerza y Resistencia: menos de 3 / End-code máx D
Inteligencia y Percepción: más de 5 y menos de 10/Rea-code máx B
Espíritu y Presencia: más de 5 menos de 9 / Esp-code min B
Esferas místicas: Sensitivity (mínimo). Escuela de magia permitida: aeromancia. Esferas místicas permitidas: healing, animismo
Habilidades especiales: invisibilidad (a voluntad, excepto cuando atacan)
Espada/Flecha de hada: daño = 2 + Str/Dex
Sus armas (pequeñas versiones de un arco o una espada larga) tienen un veneno que causa a las victimas un sueño de varias horas (tantas como una carta aleatoriamente tomada del Fate Deck en horas). Viven en unidades tribales desde una docena, hasta cientos. (excepto en Qualinesti, donde la población ha sido drásticamente diezmada). y usualmente revolotean en un claro del bosque, o pradera
Al preparar el veneno, debe hacerse un chequeo de percepción para encontrar el hongo del cual se saca el veneno (dificultad 12).
Luego se chequea destreza para preparar el veneno. El número que se saque será la dificultad del chequeo de Resistencia que deben hacer las víctimas para no caer dormidas instantáneamente. En caso de que no sea así, cada ronda pierde una carta, hasta quedar definitivamente dormida, por la cantidad de horas indicada. Sólo curación mágica puede despertar inmediatamente a una persona de este veneno.
Para evitar atacar inmediatamente, chequear Spirit contra:
naturaleza dif.
1-3 N.A.
4-9 Nature+Spi
si nature es dragon (mayor a 3) o corazón negro, la dificultad es 25 (imposible)
The Scholar-Sorcerer
By Eric Jwo
Sorcerer-Scholars are sorcerers who are devoted to studying and exploring the magic
of Krynn. While this description fits any person who wields magic to some extent, the
scholar-sorcerer is not content to merely cast balls of flame at every goblin that walks
by. The scholar-sorcerer revels in searching through ancient tomes for hours as well as
traipsing through dark ruins to search for lost secrets. They are not concerned with the
final destination as they are with the journey itself. A scholar-sorcerer is an adventurer
in the noblest sense of the word, searching for answers both in body and in mind.
Role-Playing
Scholar-Sorcerers often seem bookish and reserved to most people. People tend to
see them as thinkers, not doers. Since many adopt the belief that the Fifth Age is the
time for the Sword and the Lance, not the pen and book, scholar-sorcerers are looked
down upon.
Scholar-sorcerers value knowledge above all else. The mundane affairs of everyday life
are usually too trivial for them to bother with. In fact, many scholar-sorcerers seem
absent-minded since they forget simple matters in favor of pondering complex ideas.
However, whenever magic is involved in anything, they become very excited. New
magical discoveries are what scholar-sorcerers live for, and the very prospect of one
sends a scholar-sorcerer into a frenzy.
The only people who can identify with scholar-sorcerers are gnomes. Gnomes can
understand how expanding the mind is more important than whacking a dragon. Fellow
sorcerers can also see the value of scholar-sorcerers and envy their quest for
knowledge. The other races though, dwarves, kender, elves, humans, etc., find
scholar-sorcerers to be bookish and useless.
Requirements
A scholar-sorcerer needs to have sharpened wits in order to plumb the depths of
magic. Therefore, a scholar-sorcerer needs a minimum score of 7 in Reason and
Perception. However, a scholar-sorcerer bookish demeanor does not endear others,
imposing a maximum score of 5 in Presence. A scholar-sorcerer also does not have
time for the useless physical pursuits that may attract others. Therefore, they have a
maximum Strength and Endurance scores of 7.
A scholar-sorcerer has studied magic for most of his life. Therefore, a scholar-sorcerer
must have a minimum Reason code of "B." Since a scholar-sorcerer has no time to
learn the art of war, all Physical scores have a maximum code of "C."
Advantages
A scholar-sorcerer constantly researches and experiments with new spells. Therefore,
any attempt to research or experiment with new magic is an automatic trump bonus.
Also, any attempt to improve a scholar-sorcerer's Reason score or code gets a +1
bonus. A scholar-sorcerer also gets an automatic trump bonus to identifying magical
items and spells of the Fourth Age.
Disadvantages
A scholar-sorcerer delves into the depths of magic, but he does so to expand his
knowledge, not to learn how to kill something. Therefore, all spells designed to inflict
damage are one degree more difficult than normal (add four to the spell point total).
The Specialist Sorcerer:
In the Fourth Age, there were three magical orders - each one ruled by a god of Magic. The Order of the White Robes was guided by Solinari's good magic; the Order of the Red Robes was commanded by Lunitari's neutral magic; and the Order of the Black Robes was ruled by Nuitari's evil magic. These three order, although sisters in magic, had no other connection among themselves. They used to keep the Towers of High Sorcery and to protect magic, hunting those who didn't join any order, the rogue wizards (or mages). Among these men and women, there were the specialist wizards, users of forbidden techniques to master one School of magic instead of that schools chosen by a certain Order.
In the Fifth Age, the specialist sorcerers reappeared after the discovery of Krynn's new magic, the Sorcery. They are men and women able to wield a certain school with mastery, but they gain some penalties while dealing with other schools and/or mysticism. A specialist sorcerer is a devoted and intelligent person, therefore having at least 7 in Reason. They seldom can practice physical tasks and weapon training besides their diligent studies, so their Strength is limited to a maximum of 5. While they must cast sorcery spells to be a sorcerer, a specialist sorcerer needs at least a B code in Reason, while their lack of training causes them to have a maximum code of C in Strength. Gnomes and Humans can be specialists.
During character creation, the player names a sorcery School. From that point on, that is the School the hero mastered, and it can't be changed. A specialist sorcerer receives a bonus of -2 in all difficulties and magic costs while trying to cast or resist a spell from the School he mastered, because of his/her familiarity with that kind of magic. He/she also considers all cards (except Dragons) to be trump when casting spell from that School.
But a specialist sorcerer receives two penalties: all spells he/she casts but those from his specialized School receive a penalty of +2 to all difficulties and costs. When trying to resist a spell that is not from his/her favorite School, a specialist sorcerer receives a +2 penalty to difficulty. Also, no card he/she plays while casting other spells beyond those he/she is a specialist with is ever trump.
[>img[Arte de "Cell" en www.dlnexus.com|http://www.dlnexus.com/gfx/art/12664.jpg]]
De forma similar al [[Misticismo]], personas a lo largo de [[Krynn]] han mostrado cierta afinidad con las energías presentes en el ambiente. Sin embargo, fue [[Palin Majere]], junto al [[Hechicero Sombrío]], quien logró controlar esta nueva magia. Ante las diferencias entre esta nueva magia y la antígüa [[Alta Hechicería]], decidió junto a éste, y a [[Dalamar El Oscuro]], disolver la [[Alta Hechicería]], en lo que se llamó el "Último Cónclave de Alta Hechicería".
De forma similar al [[Misticismo]], esta nueva magia parece venir de una fuerza interior. No todos anterior mago de [[Alta Hechicería]] mostró talento para usar este poder, y muchas personas comunes y corrientes, sin ningún entrenamiento en las artes arcanas, han mostrado talento para ello. [[Palin Majere]] fundó, en las afueras de [[Solace]], la [[Academia de Hechicería]]. Esta institución de tipo académico tiene como objeto la investigación y enseñanza de la nueva hechicería a sus estudiantes. A pesar de que su director, [[Palin Majere]], es considerado el mago más poderoso sobre la faz de [[Krynn]], él mismo, oficialmente, es un estudiante más.
The Peasant Hero Role
Role-Playing
This kind of Hero comes from a village, a lone farm, a quiet place. He leaves his home to become someone important but he has always his home in his heart, in his mind. A Peasant Hero is the 'hope' of the village to be known, to fight against a Lord, save the village.
Requirements
The Social Status of a Peasant Hero must be between Slave and Commoner. This is the only requirement. Though, the Hero should have some good stats as one or two A and a 8 or 9.
Advantages
In his homeland, this Hero will get the help of his people by any means. He gains a +4 bonus for every Presence roll dealing with people in his homeland.
Disadvantages
Though, if he fails his quests or dishonered the village, the people will close their doors. They can use any kind of weapons but they prefer Very Ligh, Light and Medium weapons.
//Creación propia de Ozono, ozono27@gmail.com//
[>img[Arte por ArchTempest en Deviantart.com|http://th02.deviantart.net/fs31/300W/i/2008/223/a/c/Swashbuckler_by_ArchTempest.jpg]]
Los protagonistas de las novelas llamadas "de capa-y-espada", llamados en inglés //Swashbucklers//, son personas rudas, extrovertidas y hábiles con la espada, sable o rapier.
Se les ve combatir basándose más en la agilidad, la espectacularidad, y la picardía, que con ataques de fuerza bruta. No es raro que complementen sus ataques y defensas de espada con otras armas y defensas tales como:
*Maingauche (una especie de daga que posee dos dagas menores abiertas en un ángulo)
*Escudo (pequeño tipo //buckler//)
*Látigo
*Mosquetes (recuerdan a los mosqueteros?)
*Otro sable o espada
El arquetipo del héroe de capa-y-espada, es romántico, apasionado, aventurero, temerario e idealista. El fuerte sentido de honor y justicia, en un sentido "caballeresco", es parte esencial de la personalidad del //swashbuckler//, así como la astucia, estilo, reflejos, y capacidad de improvisar.
Típicamente el "estilo", idealismo y habilidad en armas que favorecen la agilidad por sobre la fuerza bruta, necesariamente implican una crianza en un ambiente urbano, citadino o al menos portuario.
La picardía es más probable en un marinero, o un oportunista de las calles de Palanthas, que en un bárbaro de las planicies.
La mezcla especial entre picardía, temeridad e idealismo hace que estos héroes sean proclives a meterse en problemas, y crear fama rápidamente.
Dado lo caótico de los héroes de capa-y-espada, resulta natural que haya un natural rechazo mutuo entre ellos, y las figuras de poder político, miliar, o religioso. La mayoría no tarda en ser considerado un criminal.
!Requerimientos:
Las razas proclives a este tipo de estilo de vida son los humanos, elfos, kenders, y las razas híbridas: medio-elfos y medio-kenders. Debido a la sensibilidad hacia el honor y la justicia, el código de naturaleza no debe ser mayor que 5. La rebeldía y agresividad de la personalidad de los //swashbucklers// bien merece, en general, tener una carta de //Demeanor// de valor no inferior a 4. Tener acceso a armas elegantes, cierto tipo de encanto y estilo, y ser "gente de mundo", es propio de héroes con valores de "Riqueza" no menores que 3. Gran parte del pasado de un //swashbuckler// debe haber acontecido en ambientes portuarios, populosos, y/o citadinos, por lo que, en general, está descartado que el humano sea un bárbaro, con excepción del bárbaro marinero. Se requiere de una percepción mínima de 5 y un código de percepción B, para garantizar al menos un sentido agudo. El razonamiento ágil e inventiva de un héroe de capa-y-espada requiere de un Razonamiento mínimo de 4. Este tipo de héroes no quedan anodadados ni espantados ante expresiones de hechicería, así que el código mínimo de Razonamiento debe ser D. Lo mismo es válido para el misticismo, por lo que la misma restricción es válida para Espíritu. El valor de Espíritu debe ser mínimo 4, para reflejar la intensidad emocional y voluntad. El estilo de combate basado en la agilidad y la astucia no se basa en el gran desarrollo de resistencia física, ni es compatible con personas de gran tamaño, por lo que la Resistencia no debe ser superior a 6, y al no usar armaduras muy pesadas, el código también es limitado a D. El estilo de combate requiere un mínimo conocimiento básico de armas, y mucha destreza y agilidad. Por ello, Agilidad y Destreza deben tener un valor mínimo de 5. El uso de armas que hacen daño por peso, y escudos pesados es limitado, lo cuál impide que el código de Agilidad y de Fuerza sea superior a C.
!Ventajas
Un héroe de capa-y-espada disfruta de un bono de Carta de Triunfo, siempre que realice acciones de Agilidad para esquivar, y realizar acrobacias, y acciones de Destreza para atacar, siempre y cuando use armadura Muy Ligera, y armas Ligeras. El ataque cuerpo-a-cuerpo siempre es de Destreza contra la Agilidad del contrario.
Si el Narrador lo permite, puede incluso añadirse a un ataque (una vez por escena) una bonificación igual a la presencia del héroe, siempre y cuando el ataque sea no-letal. Por ejemplo, el héroe puede querer apagar una vela con un látigo, o quitar todos los botones de la camisa del oponente.
Disfruta también de bonificación de Carta de Triunfo para acciones de Presencia asociadas al encanto y la vivacidad. Por ejemplo, para confundir a una persona con un rápido y complejo discurso (//fast-talking//), sacar información a alguien mediante una conversa casual, seducir, decir un chiste, provocar ira o "meter casquillo" (//taunt//) y fanfarronear (//bluff//).
El héroe posee bono de Carta de Triunfo para acciones de razonamiento dirigidas a recordar chismes, leyendas y rumores. En una ciudad o puerto por cada "aventura", posee una persona contacto que puede proporcionarle apoyo e información, siempre y cuando ésto no implique poner en riesgo su propio pellejo.
!Desventajas
El héroe de capa-y-espada gana enemigos rápidamente. Una vez por cada Aventura, tiene un encuentro con algún personaje enemigo, que quiere, o bien su cabeza, o bien destruírlo y humillarlo (para devolver el favor).
El rechazo ante las autoridades impide que el héroe acceda a Cartas de Triunfo en acciones de presencia ante personas de autoridad, o Riqueza mayor o igual a 8.
La pasión y entrega por el honor y la justicia en todas sus formas, le hace difícil reprimirse de tomar acción inmediata contra personas realizando abusos o injusticias. La opresión, injusticia y maltrato (en especial hacia personas indefensas), requerirá que el héroe realice una acción de Razonamiento (dificultad a juicio del Narrador), para evitar tomar acción inmediata.
Un héroe de capa-y-espada puede actuar como justiciero y rebelde de dos formas: como héroe público, o mediante una identidad secreta.
!!Héroe público
Cada vez que el héroe visita un lugar público (como una taberna, plaza, puerto o posada) que ya haya visitado anteriormente, si se encuentra frente a alguien a quien ya ha visto antes, el héroe debe realizar una acción de Razonamiento, de dificultad variable, según la frecuencia con que se han visto), para ver si puede reconocer a la persona antes de que ella lo reconozca a él. Si el héroe falla, el personaje reconoce al héroe, de alguna de las siguientes formas:
*Si fallo la acción de Razonamiento por 1 o 2 puntos, le parece vagamente familiar y no sabe dónde lo ha visto.
*Si falló por 3 a 7 puntos, significa que la persona sabe que el héroe es una persona problemática o "especial", definitivamente no-del-montón.
*Fallar por 8 o más puntos indica que el personaje sabe exactamente quién es el héroe y dónde lo ha visto (y por qué motivo su cabeza tiene precio!).
El héroe puede intentar acciones físicas o sociales para resolver la situación de alguna forma, evidentemente.
!!Héroe incógnito
El héroe debe mantener una logística para esconder su identidad (ropa, armas y montura diferentes). En todo lugar al que ya haya ido y realizado una aventura con su "disfraz", dicho ropaje es reconocido automáticamente por cualquier testigo. Automáticamente se pierde posibilidad de Cartas de Trinunfo relacionadas con Presencia, ante figuras adversas o neutrales hacia el héroe. Una vez descubierta la identidad, se corre la voz rápidamente por todos los lugares en los que realizó acciones oculto en su "disfraz", y es reconocido casi de forma automática por quienes ya le conocían, a pesar de no llevar el disfraz. El personaje automáticamente gana todas las desventajas del rol del [[Forajido]], sin ninguna de las ventajas. También pierde la mayor parte de la disposición de sus contactos a ayudarle (según criterio del Narrador).
[img[Arte de Chris Untch en www.dlnexus.com|http://www.dlnexus.com/gfx/art/10520.jpg]]
/***
|Name:|HideWhenPlugin|
|Description:|Allows conditional inclusion/exclusion in templates|
|Version:|3.1 ($Rev: 3919 $)|
|Date:|$Date: 2008-03-13 02:03:12 +1000 (Thu, 13 Mar 2008) $|
|Source:|http://mptw.tiddlyspot.com/#HideWhenPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License:|http://mptw.tiddlyspot.com/#TheBSDLicense|
For use in ViewTemplate and EditTemplate. Example usage:
{{{<div macro="showWhenTagged Task">[[TaskToolbar]]</div>}}}
{{{<div macro="showWhen tiddler.modifier == 'BartSimpson'"><img src="bart.gif"/></div>}}}
***/
//{{{
window.hideWhenLastTest = false;
window.removeElementWhen = function(test,place) {
window.hideWhenLastTest = test;
if (test) {
removeChildren(place);
place.parentNode.removeChild(place);
}
};
merge(config.macros,{
hideWhen: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( eval(paramString), place);
}},
showWhen: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( !eval(paramString), place);
}},
hideWhenTagged: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( tiddler.tags.containsAll(params), place);
}},
showWhenTagged: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( !tiddler.tags.containsAll(params), place);
}},
hideWhenTaggedAny: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( tiddler.tags.containsAny(params), place);
}},
showWhenTaggedAny: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( !tiddler.tags.containsAny(params), place);
}},
hideWhenTaggedAll: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( tiddler.tags.containsAll(params), place);
}},
showWhenTaggedAll: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( !tiddler.tags.containsAll(params), place);
}},
hideWhenExists: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( store.tiddlerExists(params[0]) || store.isShadowTiddler(params[0]), place);
}},
showWhenExists: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( !(store.tiddlerExists(params[0]) || store.isShadowTiddler(params[0])), place);
}},
hideWhenTitleIs: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( tiddler.title == params[0], place);
}},
showWhenTitleIs: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( tiddler.title != params[0], place);
}},
'else': { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( !window.hideWhenLastTest, place);
}}
});
//}}}
[>img[Arte de Irina Vargas en www.dlnexus.com|http://www.dlnexus.com/gfx/art/12893.jpg]]
(Civilizados y Bárbaros)
!Requerimientos
*Código de Resistencia (End) B máximo (si es humano bárbaro).
*Código de Percepción (Per) B máximo (si es humano civilizado).
!Ventajas
*Aumentar en uno el valor de cualquier habilidad física (si es bárbaro).
*Aumentar en uno el valor de cualquier habilidad mental (si es civilizado).
!Desventajas
*Disminuír en uno el valor de cualquier habilidad mental (Si es bárbaro).
*Disminuír en uno el valor de cualquier habilidad física (Si es civilizado).
[<img[Imágen de Amazon.com|http://ecx.images-amazon.com/images/I/61Kdb2dZWsL._SL500_AA300_.gif]]
Basado en material escrito por Steven Brown y Steve Miller para el Mazo del Destino (Fate Deck); basado a su vez en el diseño original del juego por William W. Connors.
Acá se presenta de forma resumida información sobre las reglas del Sistema SAGA en [[la caja de Dragonlance: Fifth Age|http://www.amazon.com/Dragonlance-Fifth-Age-SAGA-System/dp/0786905352/ref=sr_1_2?s=books&ie=UTF8&qid=1341190991&sr=1-2&keywords=dragonlance+fifth+age+boxed+set]] (DragonLance Quinta Era), o la [[Era de los Mortales]].
Algunas de las reglas son opcionales.
Para jugar, se necesita el mazo de [[Cartas del Destino]], en el //[[Fate Deck|http://www.amazon.com/SAGA-FATE-CARDS-Saga-Fate/dp/078691145X/ref=sr_1_1?ie=UTF8&qid=1341190873&sr=8-1&keywords=dragonlance+fate+deck]]// (TSR #9565) o en el //[[Dragonlance: Fifth Age boxed set|http://www.amazon.com/Dragonlance-Fifth-Age-SAGA-System/dp/0786905352/ref=sr_1_2?s=books&ie=UTF8&qid=1341190991&sr=1-2&keywords=dragonlance+fifth+age+boxed+set]]// (TSR #1148).
--
Para más información sobre cómo navegar en la SAGApedia, sírvase de leer la [[Ayuda]].
Material compilado por [[Ozono27|mailto:ozono27@gmail.com]] para uso en su campaña [[JuRoCE|http://sites.google.com/site/juroceweb]]
Este sitio apoya el trabajo de:
[img[http://www.dlnexus.com/gfx/site/nexus.gif][http://www.dlnexus.com]]
<<toggleSideBar . tooltip hide>>
<html><a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/3.0/"><img alt="Licencia Creative Commons" style="border-width:0" src="http://i.creativecommons.org/l/by-nc-sa/3.0/88x31.png" /></a><br /><span xmlns:dct="http://purl.org/dc/terms/" property="dct:title">SAGApedia</span> por <a xmlns:cc="http://creativecommons.org/ns#" href="http://sagapedia.tiddlyspot.com/" property="cc:attributionName" rel="cc:attributionURL">Orestes Gonzalo Manzanilla Salazar</a> se encuentra bajo una Licencia <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/3.0/">Creative Commons Atribución-NoComercial-CompartirIgual 3.0 Unported</a>.<br />Basada en una obra en <a xmlns:dct="http://purl.org/dc/terms/" href="http://www.wizards.com/" rel="dct:source">www.wizards.com</a> </html>
/***
|Name|InlineJavascriptPlugin|
|Source|http://www.TiddlyTools.com/#InlineJavascriptPlugin|
|Documentation|http://www.TiddlyTools.com/#InlineJavascriptPluginInfo|
|Version|1.9.5|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Description|Insert Javascript executable code directly into your tiddler content.|
''Call directly into TW core utility routines, define new functions, calculate values, add dynamically-generated TiddlyWiki-formatted output'' into tiddler content, or perform any other programmatic actions each time the tiddler is rendered.
!!!!!Documentation
>see [[InlineJavascriptPluginInfo]]
!!!!!Revisions
<<<
2009.04.11 [1.9.5] pass current tiddler object into wrapper code so it can be referenced from within 'onclick' scripts
2009.02.26 [1.9.4] in $(), handle leading '#' on ID for compatibility with JQuery syntax
|please see [[InlineJavascriptPluginInfo]] for additional revision details|
2005.11.08 [1.0.0] initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.InlineJavascriptPlugin= {major: 1, minor: 9, revision: 5, date: new Date(2009,4,11)};
config.formatters.push( {
name: "inlineJavascript",
match: "\\<script",
lookahead: "\\<script(?: src=\\\"((?:.|\\n)*?)\\\")?(?: label=\\\"((?:.|\\n)*?)\\\")?(?: title=\\\"((?:.|\\n)*?)\\\")?(?: key=\\\"((?:.|\\n)*?)\\\")?( show)?\\>((?:.|\\n)*?)\\</script\\>",
handler: function(w) {
var lookaheadRegExp = new RegExp(this.lookahead,"mg");
lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = lookaheadRegExp.exec(w.source)
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
var src=lookaheadMatch[1];
var label=lookaheadMatch[2];
var tip=lookaheadMatch[3];
var key=lookaheadMatch[4];
var show=lookaheadMatch[5];
var code=lookaheadMatch[6];
if (src) { // external script library
var script = document.createElement("script"); script.src = src;
document.body.appendChild(script); document.body.removeChild(script);
}
if (code) { // inline code
if (show) // display source in tiddler
wikify("{{{\n"+lookaheadMatch[0]+"\n}}}\n",w.output);
if (label) { // create 'onclick' command link
var link=createTiddlyElement(w.output,"a",null,"tiddlyLinkExisting",wikifyPlainText(label));
var fixup=code.replace(/document.write\s*\(/gi,'place.bufferedHTML+=(');
link.code="function _out(place,tiddler){"+fixup+"\n};_out(this,this.tiddler);"
link.tiddler=w.tiddler;
link.onclick=function(){
this.bufferedHTML="";
try{ var r=eval(this.code);
if(this.bufferedHTML.length || (typeof(r)==="string")&&r.length)
var s=this.parentNode.insertBefore(document.createElement("span"),this.nextSibling);
if(this.bufferedHTML.length)
s.innerHTML=this.bufferedHTML;
if((typeof(r)==="string")&&r.length) {
wikify(r,s,null,this.tiddler);
return false;
} else return r!==undefined?r:false;
} catch(e){alert(e.description||e.toString());return false;}
};
link.setAttribute("title",tip||"");
var URIcode='javascript:void(eval(decodeURIComponent(%22(function(){try{';
URIcode+=encodeURIComponent(encodeURIComponent(code.replace(/\n/g,' ')));
URIcode+='}catch(e){alert(e.description||e.toString())}})()%22)))';
link.setAttribute("href",URIcode);
link.style.cursor="pointer";
if (key) link.accessKey=key.substr(0,1); // single character only
}
else { // run script immediately
var fixup=code.replace(/document.write\s*\(/gi,'place.innerHTML+=(');
var c="function _out(place,tiddler){"+fixup+"\n};_out(w.output,w.tiddler);";
try { var out=eval(c); }
catch(e) { out=e.description?e.description:e.toString(); }
if (out && out.length) wikify(out,w.output,w.highlightRegExp,w.tiddler);
}
}
w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
}
}
} )
//}}}
// // Backward-compatibility for TW2.1.x and earlier
//{{{
if (typeof(wikifyPlainText)=="undefined") window.wikifyPlainText=function(text,limit,tiddler) {
if(limit > 0) text = text.substr(0,limit);
var wikifier = new Wikifier(text,formatter,null,tiddler);
return wikifier.wikifyPlain();
}
//}}}
// // GLOBAL FUNCTION: $(...) -- 'shorthand' convenience syntax for document.getElementById()
//{{{
if (typeof($)=='undefined') { function $(id) { return document.getElementById(id.replace(/^#/,'')); } }
//}}}
/***
|Name:|InstantTimestampPlugin|
|Description:|A handy way to insert timestamps in your tiddler content|
|Version:|1.0.10 ($Rev: 3646 $)|
|Date:|$Date: 2008-02-27 02:34:38 +1000 (Wed, 27 Feb 2008) $|
|Source:|http://mptw.tiddlyspot.com/#InstantTimestampPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License:|http://mptw.tiddlyspot.com/#TheBSDLicense|
!!Usage
If you enter {ts} in your tiddler content (without the spaces) it will be replaced with a timestamp when you save the tiddler. Full list of formats:
* {ts} or {t} -> timestamp
* {ds} or {d} -> datestamp
* !ts or !t at start of line -> !!timestamp
* !ds or !d at start of line -> !!datestamp
(I added the extra ! since that's how I like it. Remove it from translations below if required)
!!Notes
* Change the timeFormat and dateFormat below to suit your preference.
* See also http://mptw2.tiddlyspot.com/#AutoCorrectPlugin
* You could invent other translations and add them to the translations array below.
***/
//{{{
config.InstantTimestamp = {
// adjust to suit
timeFormat: 'DD/0MM/YY 0hh:0mm',
dateFormat: 'DD/0MM/YY',
translations: [
[/^!ts?$/img, "'!!{{ts{'+now.formatString(config.InstantTimestamp.timeFormat)+'}}}'"],
[/^!ds?$/img, "'!!{{ds{'+now.formatString(config.InstantTimestamp.dateFormat)+'}}}'"],
// thanks Adapted Cat
[/\{ts?\}(?!\}\})/ig,"'{{ts{'+now.formatString(config.InstantTimestamp.timeFormat)+'}}}'"],
[/\{ds?\}(?!\}\})/ig,"'{{ds{'+now.formatString(config.InstantTimestamp.dateFormat)+'}}}'"]
],
excludeTags: [
"noAutoCorrect",
"noTimestamp",
"html",
"CSS",
"css",
"systemConfig",
"systemConfigDisabled",
"zsystemConfig",
"Plugins",
"Plugin",
"plugins",
"plugin",
"javascript",
"code",
"systemTheme",
"systemPalette"
],
excludeTiddlers: [
"StyleSheet",
"StyleSheetLayout",
"StyleSheetColors",
"StyleSheetPrint"
// more?
]
};
TiddlyWiki.prototype.saveTiddler_mptw_instanttimestamp = TiddlyWiki.prototype.saveTiddler;
TiddlyWiki.prototype.saveTiddler = function(title,newTitle,newBody,modifier,modified,tags,fields,clearChangeCount,created) {
tags = tags ? tags : []; // just in case tags is null
tags = (typeof(tags) == "string") ? tags.readBracketedList() : tags;
var conf = config.InstantTimestamp;
if ( !tags.containsAny(conf.excludeTags) && !conf.excludeTiddlers.contains(newTitle) ) {
var now = new Date();
var trans = conf.translations;
for (var i=0;i<trans.length;i++) {
newBody = newBody.replace(trans[i][0], eval(trans[i][1]));
}
}
// TODO: use apply() instead of naming all args?
return this.saveTiddler_mptw_instanttimestamp(title,newTitle,newBody,modifier,modified,tags,fields,clearChangeCount,created);
}
// you can override these in StyleSheet
setStylesheet(".ts,.ds { font-style:italic; }","instantTimestampStyles");
//}}}
!Requerimientos
*Máximo valor de 7 en Resistencia (End), y 5 en Fuerza (Str)
*Mínimo valor de 7 en Razonamiento (Rea), y 5 en Espíritu (Spi)
*Máximo Código de C en Agilidad (Agi) y Resistencia (End)
*Mínimo Código de B en Razonamiento (Rea) y Espíritu (Spi)
!Ventajas
*Puede manejar 4 escuelas de hechicería. Siempre una debe ser [[Encantamiento]]
*Puede manejar 4 escuelas de misticismo. Siempre una debe ser [[Alteración]]
*Todas las acciones de Razonamiento (Rea) y Espíritu (Spi) reciben de bono Carta de Triunfo.
!Desventajas
*Ninguna acción física podrá recibir jamás una Carta de Triunfo.
[>img[Imagen de Sandara3 en www.dlnexus.com|http://www.dlnexus.com/gfx/art/11727.jpg]]
(Verdaderos y Afligidos)
!Requerimientos
*Valor Mínimo de 7 en Agilidad (Agi), Destreza (Dex)
*Valor Mínimo de 6 en Percepción o Presencia
*Valor Máximo de 6 en Resistencia (End), Fuerza (Str)
*Código D Máximo en Agilidad (Agi)
*Código D Máximo en Resistencia (End) si es un Kender Verdadero, o C si es un Kender Afligido.
*Código B Mínimo en Percepción (Vista Aguda).
!Ventajas
*Apropiación, es decir, carta de Triunfo automática en arrebatones y prestidigitación si es Kender Verdadero
*Carta de Triunfo automática en acciones subrepticias si es Kender Afligido
*Carta de Triunfo para acciones provocadoras (//Taunting//) {{{regla de la casa}}}
*Suertudo, carta de Triunfo para evitar ser golpeado físicamente y resistir magia {{{regla de la casa}}}
*Aleatoriamete Narrador puede determinar si entre las posesiones de un kender está un objeto que sea necesario para el grupo aventurero, si es un Kender Verdadero {{{regla de la casa}}}
*Carta de Triunfo automática en acciones para resistir miedo normal o mágico {{{regla de la casa}}}
!Desventajas
*Poca concentración, es decir, código A permitido sólo en Percepción (Per)
*Toda acción fallida relacionada con magia es una [[Desgracia]] (//Mishap//) {{{regla de la casa}}}
*Jamás reciben Carta de Triunfo en acciones de Presencia con no-kenders para generar confianza o ser tomado en serio, si es Kender Verdadero {{{regla de la casa}}}
*Jamás recibe Carta de Triunfo en acciones de Espíritu para resistir miedos y tristezas asociado a recuerdos de catástrofes en Kendermore, si es afligido {{{regla de la casa}}}
*Debe realizar acción de Razonamiento (Rea) a dificultad arbitrariamente determinada por el Narrador, para evitar apropiarse de objetos "curiosos", o desviarse por caminos "interesantes", si es Kender Verdadero {{{regla de la casa}}}
El área que rodea a la Fortaleza de Daargaard, y que alguna vez gobernara Lord Soth, ahora ha recibido el nombre de Nightlund, debido a su perpetua penumbra (//night// significa "noche"). El área está plagada de [[Muertos Vivientes]] y el [[Río Vingaard]] está inundado de piratas [[Muertos Vivientes]].
Las planicies de [[Throt]] yacen ante las faldas de las [[Montañas Dargaard]], y sirven de amortiguador entre las fuerzas de [[Solamnia]] y [[Neraka]]. El gobernante es un [[Hobgoblin|Hobgoblins]] llamado Uhkrin, quien ha sellado un pacto con [[Neraka]] para permitirle utilizar sus puertos, a cambio de apoyo militar en caso de una invasión desde [[Solamnia]]
Originalmente hubo sólo una orden de caballería, que se hicieron llamar los [[Caballeros de Solamnia]], una orden originaria de la región llamada [[Solamnia]], dedicada a las virtudes del bien y la justicia. En la [[Guerra de Caos]] surgió, en inspiración de los [[Caballeros de Solamnia]], pero con dedicación a la diosa de la maldad, [[Takhisis]], la orden de los [[Caballeros de Takhisis]].
La [[Guerra de Caos]] fue "ganada" (hay teorías al respecto!) debido a la lucha en conjunto de [[Caballeros de Solamnia]] y [[Caballeros de Takhisis]], junto a hechiceros de [[Alta Hechicería]]. Quien liderizó ese ataque conjunto fue el Caballero de Takhisis [[Steel Brightblade]], hijo de [[Sturm Brightblade]]. En su honor, surgió en la 5ta Era, la que ha sido llamada la [[Legión de Steel]], dedicada a la justicia y la virtud en todas sus formas, y a la unión y colaboración mutua de los pueblos de Krynn. Su lema principal es "Todo lo que tenemos, es a nosotros mismos".
Durante la [[Guerra de Caos]], también llamado el "Verano de Caos", los dioses de la magia desaparecieron (al igual que los demás dioses). Ellos brindaban poderes mágicos a los hechiceros de las anteriores eras en [[Krynn]], y al irse se llevaron con ellos ese poder. Todos los magos quedaron vacíos de magia, salvo la suficientemente insignificante como para no requerir la intervención de los dioses.
Las [[3 lunas|Lunas de la Magia]], que correspondían a los 3 dioses de la magia, [[Solinari]], [[Lunitari]] y [[Solinari]], fueron reemplazadas por una simple y pálida luna, que no les proporcionaba poder alguno. Los clérigos también perdieron su magia, ya que nadie contestaba sus oraciones.
La magia en si no desapareció, sin embargo. Hubo siempre, a lo largo de la historia de [[Krynn]], personas que tenían una habilidad innata para manejar cierto poder mágico. Brujerías, adivinos, algunos bardos, druidas y mediums son ejemplos de ésto, aún cuando con frecuencia complementaran sus acciones con engaño y carisma pura. También continuó habiendo magia en los seres cuya naturaleza intrínseca implicaba el uso de la magia, como lo son los [[Dragones]].
Esta [[magia|Magia Primordial]] "primordial" fue objeto de persecución durante años por parte de la [[Alta Hechicería]], quienes forzaban a quienes no respetaran sus reglas, a plegarse a éstas o morir. El motivo detrás de la persecución de esta magia "salvaje" estaba en que la [[Alta Hechicería]] garantizaba un uso "controlado" de la magia, y un respeto intrínsico a ésta en todas sus formas. En tiempos antigüos, antes de surgir la [[Alta Hechicería]], los magos salvajes habían puesto en peligro la vida en todo [[Krynn]], en su intento descontrolado por controlar los elementos en la guerra contra los [[Dragones]].
Las formas de magia innatas que han surgido (nuevamente, según ciertas teorías) en la 5ta Era, son el [[Misticismo]] y la [[Hechicería]].
Guild Thief
Ability Scores Ability Codes Other Req.’s Advantages Disadvantages
Any. “B” min. in Dx Nature 5 max. Trump for Re, Pe, or Dx Challenging Re action to
or Pe or Re wealth between thief actions; hand talk; avoid rash behavior to
4 and 6. can acquire role during oppose injustice
play. or oppression.
El narrador utiliza las características del texto escrito en la carta para determinar el éxito. Por ejemplo: el héroe intenta resistir a la tortura que le hace el enemigo para extraer información. El jugador puede anunciar que desea hacer una lectura de inscripción. Si el narrador acepta, y le jugador utiliza la carta de Flint Fireforge ("Determinado y de Gran Corazón") para su accion, el narrador puede concordar con el jugador en que la carta está especialmente acorde con la situación, y por lo tanto considerar la acción un éxito. El roleplay o actuación del personaje debe reflejar la inscripción, de alguna forma. Si ambas palabras aplican, la situación es un éxito. Si sólo una aplica, es un éxito parcial.
El narrador puede aceptar la petición, bajo condición de que todos hagan un check en esa oportunidad, bajo el mismo método, de forma que si al menos un personaje se niega, el método no se utiliza. También, puede limitar su uso a 3 veces por cada sesión de juego, o una vez por escena.
En una ocasión por casa escena del juego, todo jugador puede solicitar, para la resolución de una acción, una lectura de "personaje".
Esto funciona de la siguiente manera. Dado que el jugador tiene algo de conocimiento sobre los personajes que están representados en las cartas que tiene en mano, es posible que pueda identificar que uno de los personajes sería muy apropiado para ser "llamado" a hacer esa acción, o sería muy sencilla para ese personaje el realizarla. Como ejemplo, supongamos que se trata de una acción para abrir una cerradura. Un jugador con la carta que tiene representado a Tasslehoff Burrfoot, podría solicitar una lectura del personaje de esa carta y tener garantizada esa acción, con resultados excelentes.
Si el personaje tiene cierta capacidad en esa área, pero no es sobresaliente en particular por ello, podría darse como "pasada" la acción, sin resultados espectaculares.
Si por el contrario el personaje sería más bien inepto o incapaz de realizar la acción, el chequeo sería considerado un fallo.
El significado de los [[Elementos de las cartas]] están acá, y son utilizados para la mayor parte de las acciones, de la forma mencionada en [[Ejecutando Acciones]].
Sin embargo, a veces se hacen otros tipos de checks:
*Lecturas de [[Aura|Aura de una carta]]
*Lectura de [[inscripción|Lectura de Inscripción de una Carta]]
*Lecturas de [[Personaje|Lectura de Personajes de Cartas]]
*Lecturas de [[Pinta|Pinta de las cartas]]
*[[Cartas al Azar]]
[>img[Arte de David Davidson en www.dlnexus.com|http://www.dlnexus.com/gfx/art/10481.jpg]]
Sir [[Steel Brightblade]], hijo del Héroe de la Lanza [[Sturm Brightblade]], fue criado en adopción por Sara Dunstan. Ella, tras finalizar la [[Guerra de Caos]] y la muerte de [[Steel|Steel Brightblade]], recibió una visión de él. Su fantasma o espíritu se presentó ante ella y a raíz de lo que él le comunicó en ese momento, ella fundó la Legión de Steel. Su símbolo es el pendiente élfico que [[Steel|Steel Brightblade]] heredara de su padre, quién a su vez lo recibiera de la princesa elfa [[Alhana Starbreeze]]. Este pendiente, según la tradición élfica, es entregado a la persona a la que se amará por el resto de la vida. Por ello, es un símbolo de unión, amor, y compromiso.
La Legión estaba dedicada al bien común de los pueblos de Krynn, y lógicamente fue integrada principalmente (al menos en su inicio) por [[Caballeros de Takhisis]] y [[Caballeros de Solamnia]] que sentían que las formas de actuar de sus respectivas órdenes no eran correctas. Ambas órdenes continúan siendo de funcionamiento rígido, y dedican bastante de su tiempo en las discusiones sobre lo que es bueno, y lo que es malo, cada cual desde su perspectiva.
La perspectiva de la Legión de Steel, es que la virtud puede hallarse y expresarse de muchas formas. No necesariamente dentro de una brillante armadura, convencida de que el bien está de su lado. El Cuartel General está cerca de Solace, que es donde yacen los restos de Sir Steel Brightblade. La mayoría de las ciudades y pueblos de Ansalon poseen, o bien guarniciones oficiales, o células de legionarios encubiertos.
La Legión oficialmente es neutral ante los [[Caballeros de Takhisis]] y de [[Solamnia|Caballeros de Solamnia]], pero el hecho de que los [[Caballeros de Takhisis]] tengan pena de muerte sobre los desertores, hace que haya serios conflictos. Las luchas entre [[Caballeros de Solamnia]] y los Legionarios, si ocurren, se dan cuando se elevan mucho los ánimos en las discusiones sobre cuál de las dos órdenes hace mayor bien a Krynn.
En las filas de los Legionarios se encuentran miembros de diversas razas Ansalonianas, así como [[Hechiceros|Hechiceros Legionarios]], [[Místicos|Místicos Legionarios]], y [[Exploradores|Exploradores Legionarios]].
Se rigen por los [[6 principios|Principios de la Legión de Steel]].
/***
|Name:|LessBackupsPlugin|
|Description:|Intelligently limit the number of backup files you create|
|Version:|3.0.1 ($Rev: 2320 $)|
|Date:|$Date: 2007-06-18 22:37:46 +1000 (Mon, 18 Jun 2007) $|
|Source:|http://mptw.tiddlyspot.com/#LessBackupsPlugin|
|Author:|Simon Baird|
|Email:|simon.baird@gmail.com|
|License:|http://mptw.tiddlyspot.com/#TheBSDLicense|
!!Description
You end up with just backup one per year, per month, per weekday, per hour, minute, and second. So total number won't exceed about 200 or so. Can be reduced by commenting out the seconds/minutes/hours line from modes array
!!Notes
Works in IE and Firefox only. Algorithm by Daniel Baird. IE specific code by by Saq Imtiaz.
***/
//{{{
var MINS = 60 * 1000;
var HOURS = 60 * MINS;
var DAYS = 24 * HOURS;
if (!config.lessBackups) {
config.lessBackups = {
// comment out the ones you don't want or set config.lessBackups.modes in your 'tweaks' plugin
modes: [
["YYYY", 365*DAYS], // one per year for ever
["MMM", 31*DAYS], // one per month
["ddd", 7*DAYS], // one per weekday
//["d0DD", 1*DAYS], // one per day of month
["h0hh", 24*HOURS], // one per hour
["m0mm", 1*HOURS], // one per minute
["s0ss", 1*MINS], // one per second
["latest",0] // always keep last version. (leave this).
]
};
}
window.getSpecialBackupPath = function(backupPath) {
var now = new Date();
var modes = config.lessBackups.modes;
for (var i=0;i<modes.length;i++) {
// the filename we will try
var specialBackupPath = backupPath.replace(/(\.)([0-9]+\.[0-9]+)(\.html)$/,
'$1'+now.formatString(modes[i][0]).toLowerCase()+'$3')
// open the file
try {
if (config.browser.isIE) {
var fsobject = new ActiveXObject("Scripting.FileSystemObject")
var fileExists = fsobject.FileExists(specialBackupPath);
if (fileExists) {
var fileObject = fsobject.GetFile(specialBackupPath);
var modDate = new Date(fileObject.DateLastModified).valueOf();
}
}
else {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
file.initWithPath(specialBackupPath);
var fileExists = file.exists();
if (fileExists) {
var modDate = file.lastModifiedTime;
}
}
}
catch(e) {
// give up
return backupPath;
}
// expiry is used to tell if it's an 'old' one. Eg, if the month is June and there is a
// June file on disk that's more than an month old then it must be stale so overwrite
// note that "latest" should be always written because the expiration period is zero (see above)
var expiry = new Date(modDate + modes[i][1]);
if (!fileExists || now > expiry)
return specialBackupPath;
}
}
// hijack the core function
window.getBackupPath_mptw_orig = window.getBackupPath;
window.getBackupPath = function(localPath) {
return getSpecialBackupPath(getBackupPath_mptw_orig(localPath));
}
//}}}
/***
|''Name:''|LoadRemoteFileThroughProxy (previous LoadRemoteFileHijack)|
|''Description:''|When the TiddlyWiki file is located on the web (view over http) the content of [[SiteProxy]] tiddler is added in front of the file url. If [[SiteProxy]] does not exist "/proxy/" is added. |
|''Version:''|1.1.0|
|''Date:''|mar 17, 2007|
|''Source:''|http://tiddlywiki.bidix.info/#LoadRemoteFileHijack|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0|
***/
//{{{
version.extensions.LoadRemoteFileThroughProxy = {
major: 1, minor: 1, revision: 0,
date: new Date("mar 17, 2007"),
source: "http://tiddlywiki.bidix.info/#LoadRemoteFileThroughProxy"};
if (!window.bidix) window.bidix = {}; // bidix namespace
if (!bidix.core) bidix.core = {};
bidix.core.loadRemoteFile = loadRemoteFile;
loadRemoteFile = function(url,callback,params)
{
if ((document.location.toString().substr(0,4) == "http") && (url.substr(0,4) == "http")){
url = store.getTiddlerText("SiteProxy", "/proxy/") + url;
}
return bidix.core.loadRemoteFile(url,callback,params);
}
//}}}
Los Draconianos, producto de un oscuro ritual realizado sobre huevos de dragones metálicos, han ido reduciendo sus números. Fueron creados con magia, sin la capacidad de reducirse, por lo que poco a poco han ido muriendo por diferentes razones a lo largo de los años. La diosa Takhisis y sus grandes ejércitos ya no existen, y los caballeros de takhisis no parecen tener mucho uso para ellos. Se les encuentra vagabundeando, asaltando, bebiendo, o simplemente sobreviviendo una vida sin sentido, y sin compasión. Son vistos casi inequívocamente como mounstros malignos, y en realidad así fueron creados y criados.
Sin embargo, hay rumores de que un grupo de Draconianos, en un acto de verdadero altruísmo, han logrado producir Draconianas (de sexo femenino), a partir de algunos huevos de dragón que no fueron utilizados en su momento. Aparentemente se han establecido en la nación de [[Teyr]], al norte de [[Neraka]] y al oeste de las [[Montañas de Avistar]]. Aparentemente el líder se hace llamar Lord Kang.
La tierra de [[Neraka]], centro de operaciones de los [[Caballeros de Takhisis]], ahora rinde vasallaje a los caballeros oscuros, por lo cuál los Draconianos han pedido ayuda a los [[Caballeros de Solamnia]], solicitud que no ha tenido una respuesta positiva, por motivos obvios.
[>img[Arte de PsychaDurmont en www.dlnexus.com|http://www.dlnexus.com/gfx/art/19683.jpg]]
La historia de los elfos ha estado llena, durante cientos de años, de guerras civiles entre las tres diferentes sub-razas, y la 5ta Era no es la excepción. Un grupo de Senadores y Milicia tanto de [[Qualinesti]] como de [[Silvanesti]] dieron un golpe de estado a [[Alhana Starbreeze]] y su esposo [[Porthios Khanan]] de sus tronos, y los expulsaron tildándolos de [[Elfos Oscuros]], antes de que su hijo [[Silvanoshei]] naciera. Siendo ambos los legítimos herederos de los tronos de [[Silvanesti]] y [[Qualinesti]], su hijo sería quien finalmente uniría ambos reinos. Sin embargo esto no pareció conveniente a aquellos con sed de poder, o extremo apego a las estrictas reglas de aislamiento y separación.
Por su lado, los elfos salvajes [[Kagonesti]], no han tenido paz. Algunos participan dando apoyo a quienes luchan en contra de [[Beryl]] en [[Qualinost]], otros apoyan a [[Porthios|Porthios Khanan]] y [[Alhana|Alhana Starbreeze]], pero la mayoría perdieron su vida luchando contra el Señor Dragon Gelidus, en su tierra natal. Es de la creencia de la mayoría de los [[Kagonesti]], que su alma gemela es un árbol en [[Ergoth del Sur]]. Estas junglas, antes rebozantes de verdor, ahora están convertidas en una estepa gélida e inhóspita.
[>img[Arte de Thor (the powerhead) en www.dlnexus.com|http://www.dlnexus.com/gfx/art/11608.jpg]]
Grandes crisis han golpeado a los Enanos desde que terminó la 4ta Era. En Thorbadin hubo una fuerte división entre los clanes. La antígüa morada de los [[Hylar]], el Árbol de la Vida, ha sido destruído, y la mayoría de Thorbadín yace en ruinas. Muchos huyeron a [[Thoradin]], con su líder [[Severus Stonehand]], un enano [[Daewar]], para reclamarla. [[Thoradin]] había sido tomada por los [[Zakhar]] hacía tiempo. Éstos a su vez huyeron a las montañas adyacentes. [[Stonehand|Severus Stonehand]] sorpresivamente forjó una alianza con los [[Caballeros de Takhisis]], como parte de su estrategia para restablecer el poder y el orden de su clan.
Los enanos que quedaron en [[Thorbadin]], liderizados por el Thane [[Glade Hornfel]] cerraron nuevamente las puertas, aislándose del resto del mundo, para protegerse del Señor Dragón [[Beryl]], también llamado "La Amenaza Verde". Nadie ha sabido de ellos, aunque hay rumores de un pacto secreto entre ellos y el Príncipe [[Gilthas de Qualinesti]].
Los [[Enanos de las Colinas]] han sido forzados a huír al norte de [[Abanisinia]], para refugiarse de los ataques de [[Beryl]].
Los Gnomos del [[Monte Noimporta]] fueron aterrorizados por un gran dragón rojo llamado Pyrothraxus, también llamado [[Pyro]]. Cuando se encontró por primera vez con los Gnomos, [[Pyro]] se enfureció porque los gnomos, en lugar de huir despavoridos rogando por sus vidas, deseaban estudiarlo para encontrar su mecanismo de combustión interna. El dragón enloqueció de rabia y se negó a irse, hasta que pudiera derroar a los gnomos. Con el pasar del tiempo, [[Pyro]] se ha vuelto literalmente demente, por las acciones de los inventivos gnomos.
[[Chaos]] trajo muchos cambios sobre las razas de [[Krynn]], pero uno de los más inusuales ha sido la transformación de un grupo de gnomos. Éstos ahora construyen artefactos que realmente funcionan! Son conocidos como [[Gnomos Pensadores]]. Los Gnomos tradicionales aún se ven en Ansalon, pero son ahora conocidos como [[Gnomos Inventores]] (traducción de //tinker gnomes//... otra alternativa es Gnomos Dizqueingenieros, Hojalateros, Ingenieretes, Ingenieruchos).
Con la llegada de los Señores Dragones, Kendermore fue uno de los primeros sitios devastados. Miles de kenders huyeron en éxodo por todo [[Ansalon]], y muchos se asentaron en [[Hylo]], en [[Ergoth del Norte]].
Algunos kenders, que presenciaron la masacre, fueron capaces de sentir por primera vez en sus vidas la sensación del miedo. Se convirtieron en lo que ahora se denomina "Kenders Aflijidos". Son mucho más serios y precavidos.
At the close of the battle, one group of combatants has bested the other. But before the scenario can continue, there are a few loose ends to tie up.
Coup de grâce
Healing:
After almost every battle, some or all the heroes will be wounded. How quickly they recover from these wounds will greatly affect their future adventures. When a hero's hand has been restored to its full size, the hero is completely healed.
First aid:
Immediately after the battle ends, a hero may receive basic medical attention. If any other hero succeeds at an average Dexterity action to give first aid (bind the wounds to avert the immediate threat), the hero recovers enough for the player to regain one card for his or her depleted hand.
Natural healing:
Time heals all wounds. However, it does so very slowly. For every week that passes during the adventure, a wounded hero recovers one card through natural healing.
Magical healing:
Those skilled in the mystical magic of healing can heal a hero instantly and completely. As a rule, giving one card's worth of magical healing requires a challenging Spirit action from the hero using the magic (details of this and other aspects of magic appear in the next section).
Spoils:
As the adage says, "To the victors go the spoils." After any battle, the slain or unconscious foes will have some valuable equipment. The heroes may do with these items what they want, but the players should remember that they are playing heroes, not thieves. Most published scenarios will list the important items to be found after a battle, though the Narrator can always adjust this list to suit the needs of the game.
A menos que se diga lo contrario por algún motivo específico, el líder es quien tenga la Presencia más alta. Esto es algo que aplica sólo para fines militares.
MPTW is a distribution or edition of TiddlyWiki that includes a standard TiddlyWiki core packaged with some plugins designed to improve usability and provide a better way to organise your information. For more information see http://mptw.tiddlyspot.com/.
[img[Arte de Eriane Blais en www.dlnexus.com|http://www.dlnexus.com/gfx/art/22971.jpg]]
Heroes with Reason or Spirit ability codes of "A" or "B" have the skill necessary to cast magical spells. There are two forms of magic in this game, sorcery and mysticism. The schools of sorcery or spheres of mysticism a hero knows (if any) are mentioned on the back of the Character Card or on the hero description sheet. These do not change during play.
Sorcery
Sorcery draws upon the magical energy left over from when the world was formed from primordial chaos. It can affect only inert matter and the elements; it cannot directly affect living things. Heroes with high Reason codes have been trained in the use of sorcery. The art of sorcery is divided into eleven schools: aeromancy (spells of air and wind), cryomancy (spells of cold), divination (see the past or future or detect the unseen), electromancy (electrical magic), enchantment (make magical items), geomancy (spells of earth and rock), hydromancy (spells of water), pyromancy (spells of fire), spectramancy (spells of light and illusion), summoning (magical transport), and transmutation (changing matter).
Mysticism
Mysticism draws upon the power of life and the spiritual energies of its practitioners. It affects only living or once-living beings. Heroes with high Spirit codes have been trained in the use of mysticism. Mysticism is divided into nine spheres: alteration (shapechanging powers), animism (talk to, control, or mimic plants and animals), channeling (raise or lower Physical ability scores), healing (heal illnesses or wounds), meditation (raise or lower mental ability scores), mentalism (telepathy), necromancy (cause magical injury and create undead creatures), sensitivity (read auras), and spiritualism (talk to spirits and create undead spirits).
[[Wielding Magic]]
The Shadowmage
The shadowmage is a member of the Obsidian Order. They don't refer to themselves as "shadowmages", but people who see them do. Shadowmages are always dressed in black robes (note: this does not denote any devotion to the black robes of High Sorcery or Nuitari). Members of the Obsidian Order have access to some of the greatest sorcerous power on Krynn (see: The Obsidian Order). Only those who are serious about studying sorcery, and have the aptitude to control magic are admitted to the Order. The Order finds and teaches such men and women from youth. Every member is expected to devote himself to the research of sorcery, and to help Shade in his plan. Only someone who is dedicated to magic is chosen.
Role Playing:
Shadowmages are very serious about sorcery. They will not stand to see it abused. They have devoted their entire lives to discovering more about it, and take their jobss very seriously.
There are two types of shadowmages. One stays deep in the Dwelling, the Order's underground headquarters. There they spend their time experimanting with magic, creating enchanted items, and helping Shade open a gate to his home plane. The second goes out into the world to further the Order's knowledge of sorcery. Whether they have specific missions, or are just told to further the Order's cause, any information gathered on sorcery or portals should be immediantly relayed back to members in the Dwelling.
Heroes with this role must keep two things in mind, and follow them above all else:
1) Furthering the knowledge and use of sorcery on Krynn, and
2) Opening a gate to Shade's realm. Personal feelings need not be thrown away, as long as they do not hinder the two goals. Therefore, a shadowmage may oppose the Dragon Overlords and champion the oppresed as long as it does not interfere with his primary goals.
Shadowmages are very secretive, and never let anyone, even close friends, or other heroes know that they are shadowmages, or even that the Obsidian Order exists. The Order has forbidden a shadow mage to tell anyone.
Requiremnets:
The Order only recruits men and women with high sorcerous potential. To be a shadowmage, a hero must have a Reason score of 6 or higher, and a Reason code of "A." Those who don't are overlooked.
Any race can join the Obsidian Order, with the obvious exceptions of races who can't wield sorcery at this level. A shadowmage must have the school of enchantment, as that is the first school that the Order teaches an Initiaate. As the Order recruits at an early age, a hero cannot acquire this role during play.
Advantages:
As master enchanters, a shadowmage has an automatic Trump bonus whenever he casts a spell from the school of Enchantment. He also gets a magical trinket (see: Magical Items of the Obsidian Order) upon beginning of play.
Disadvantages:
A shadow mage never gains a Trump bonus when he casts a damaging spell. Because of a shadowmage's strange manner, he never gets a Trump bonus to Presence actions (except when resisting mysticism) against anyone except fellow shadowmages.
Storm Mage
The Storm Mage is a sorcerer adept at casting spells that involve the fury of a storm. The can call into being great storm clouds and summon bolts of lightning to strike down their enemies from the sky. Sorcerers like the mage Daeyin are Storm Mages.
Dwarves, gnomes and true kender may not be storm mages.
Role Playing:
The Storm Mage finds himself at home in the heart of a great gale, and could not be more comfortable than when he is sitting at home listening to the sound of rain outside his door. They are fascinated by the great sounds of thunder and flashes of lightning.
The Storm Mage's personality reflects that of his passion. Like the storm, he can be calm and bring good to the world (just as a storm bring water to fields), but can turn violent and angry (many have been described as being in a stormy mood) at even the slightest annoyance. Most Storm Mages, though, control their anger, and use it appropriately and quickly. It is a rare Storm Mage that keeps a grudge.
This type of sorcerer typically prefers dark blues and grays (although some flashier ones have been known to wear yellow sashes to symbolize lightning), and often has a "dark" look to him.
Requirements:
Like the storm, the Storm Mage flows and moves like the air. To reflect this, he must have a minimum Agility of 6. However, since missile weapons rarely work during great storms, the sorcerer have an ability code in Dexterity higher than "C". Though the Storm Mage can be quite strong, he prefers light weapons, especially those that are thin and quick (such as a rapier or stiletto). As such he cannot have an ability code in Strength higher than "C". Such large weapons he finds to bulky for good use. To reflect his sorcery training, the Mage must have an ability code of "A" in Reason. And Due to his Extreme personality, and minimum of 6 in Presence. In addtion, because of unpredictable nature, the Storm Mage must choose his Nature and Demeanor.
Ability Score Code
Agility 6 min -
Dexterity - C Max
Strength - C Max
Reason - A Min
Presence 6 min -
Nature & Demeanor Red Auras only
Advantages:
Due to his affinity with storms, the Storm Mage gains an automatic trump while casting spells during them, or during any time where winds reach higher than 20mph. He also gains an automatic trump in the school of Aeromancy. Heroes may acquire this role during play. Disadvantages Due to emphasis on storms, the Storm Mage must learn at least one of the following schools: Aeromancy, Electromancy, or Conjuration. But, he may never cast spells from the schools of Geomancy, Pyromancy, or Transmutation.
[>img[Arte de Jennifer Meyer en www.dlnexus.com|http://www.dlnexus.com/gfx/art/22479.jpg]]Spellfilch
Recent years have seen the emergence of a new stripe of thief, who draws upon sorcery and mysticism to increase his thieving skill. From spells that make victims temporarily forget a robbery to castings that make walls as insubstan-tial as air, these spellfilches devote their arcane talents to helping them make a living off other people's property.
Role-playing:
The reasons for thievery vary from thief to thief; one might discover virtually as many different motiva-tions as there are thieves. Heroes with this role generally focus their efforts on stealing from high-ranking Evil characters.
In general, thieves seem a self-assured bunch. However, the magical skill of a spellfilch usually makes him ten times as cocky as the average thief. Many of them leave "signatures" behind at the scenes of their crimes. For example, one infamous spellfilch known as the Ice Lady takes her name from the tiny, intricately carved ice fig-urines of an elf maiden she always leaves at her robbery sites.
These heroes generally know their limitations, but they invariably try to take charge of any group they join. A spellfilch knows he's the best there is.
Note: Most thieves do not steal from friends and allies. Realizing that everyone needs someone to draw upon in times of need, these heroes should never intentionally alienate those who could lend them such support.
Requirements:
Spellfilches must have at least a "B" code in Reason or Spirit and a Dexter-ity score of at least 4.
Furthermore, the player must define his hero's "signature." It should be something small and relatively simple yet entirely distinctive, to show the world who committed the crime.
Advantages:
Any card played for the hero to use a spell in thief activities-such as picking locks, disarming traps, and so on-is considered automatic trump.
Disadvantages:
Due to their flamboyant nature, spell-filches tend to make enemies. One such enemy doggedly tries hunting the hero down. Although this charac-ter might not know what the hero looks like, he may nonetheless close in by following the trail of signature crimes. The Narrator and player should work together to determine this pursuer's identity.
Heroes can adopt this role during play only after previously playing a dif-ferent roguish role.
[[Inicio]]
[[Creación de Héroes]]
[[Habilidades]]
[[Razas]]
[[Roles]]
[[Magia]]
[[Terminología]]
[[Combate]]
[[Acciones Heróicas]]
[[Ayuda]]
[[Contácteme|mailto:ozono27@gmail.com]]
<<toggleSideBar . tooltip hide>>
Thug
Ability Scores Ability Codes Other Req.’s Advantages Disadvantages
Any. Any. Demeanor 6 min. Easy Pr action to Honorable characters will
intimidate foe with lower challenge bullying thugs
St score; proper to a duel.
personality can acquire
roll during play.
[>img[Arte de Nick Barfuss en www.dlnexus.com|http://www.dlnexus.com/gfx/art/19661.jpg]]
!Requerimientos
*Dos valores mínimos élficos
*Un valor máximo élfico
*Código B mínimo en Destreza (Dex) o Fuerza (Str)
!Ventajas
*Escoger una ventaja élfica
!Desventajas
*Jamás podrá usar Carta de Triunfo en acciones e Presencia relacionadas con trato con elfos (excepto para resistir [[Misticismo]]
!Requerimientos
*Tres requerimientos de valores de los [[Elfos Kalanesti]].
*Un mínimo de Código de Kalanesti, y un máximo de código.
!Ventajas
Escoger ventajas Kalanesti sobre la base del tiempo que se ha vivido entre Kalanestis (en ningún caso puede disfrutar de la ventaja de encantar las flechas, a menos que posea la esfera de encantamiento, y formule el hechizo).
!Desventajas
*No puede utilizar Cartas de Triunfo para acciones de Presencia en relaciones con elfos (excepto para resistir misticismo).
*Escoger otras desventajas Kalanesti en función del tiempo que se ha vivido entre Kalanestis.
[>img[Arte de Brett Wiseman en www.dlnexus.com|http://www.dlnexus.com/gfx/art/12808.jpg]]
!Requerimientos
*Valor máximo de 5 en Agilidad (Agi) y Destreza (Dex)
*Valor mínimo de 8 en Resistencia (End) y Fuerza (Str)
*Código mínimo de B en Resistencia (End) y Fuerza (Str)
*Código máximo de C en Razonamiento (Rea) o en Espíritu (Spi) (debe escogerse uno al crear el personaje)
!Ventajas
*Disfruta de Carta de Triunfo siempre en acciones náuticas y demostraciones de ferocidad (acciones de Presencia para intimidación, por ejemplo)
!Desventajas
*Jamás podrá usar Cartas de Triunfo en acciones de Presencia (Pre) con otras razas (excepto las hostiles).
Of all the Masters who have emerged from the crystal domes of Schallsea to teach mysticism to the world and change the hearts and minds of the people, only the very strongest can become Citadel missionaries.
Role Playing:
Missionaries are wandering mystics, many of whom travel in lands ruled by Great Dragons or by governments who refuse the Citadel´s message. By teaching the common folk in these lands to open themselves to the power of the heart, they give the downtrodden hope for the future and the best weapon with wich to fight the tyrants for whom they labor.
These heroes share a few common traits. First they have a no-nonsense attitude that allows them to accomplish feats that few others would even think to try. They have a tenacity that keeps them going even in the face of great danger or terrible odds. And, lastly, these self-sacrificing individuals have a spirit of optimism and hope for the future that never dies.
Requirements:
These Citadel mystics have at least a Spirit code of “B” and score of 5. They need scores of 5 or better in Reason and Presence as well, due to the constant pressures of their missions –they must be able to convince doubters of the truth about the power of the heart through logic, by inspiration born of personal conviction, or by performing miracles. Frequently, all three tactics come into play, for missionaries must daily deal with individuals whose belief in a traditional religion is as strong as their own faith in Goldmoon´s message.
Missionaries are usually given extra defensive training before journeying into hostile area. Therefore, they need not to conform to the usual Citadel Physical code standards. Instead, they have no code limit on their Agility and Endurance and may have as high as “B” code in Strength and Dexterity.
Only Master mystics –those who have achieved Master reputation and defeated their personal demons atop the Silver Stair- can be Missionaries.
Advantages:
Missionaries are highly effective debaters and experts in philosophy. When engaging in philosophical or moral discussions, they always enjoy a trumb bonus for Reason actions. This expertise can also become the voice of reason to help calm mobs of peasants and even argue down officials bento on executing or imprisoning the missionary or other Citadel followers.
The difficulty of such actions (wich are generally opposed) varies based on the beliefs of the characters involved and/or the severity of the hero´s alleged offenses. A mishap at this action immediatly turns even neutral listeners vehemently –and sometimes violently- against the missionary and his or her message.
Heroes who meet the role´s requirements can become Citadel missionaries during play.
Advantages:
While followers of the Citadel know they will always have a home in Schallea, mystics who become missionaries rarely go there. And when they do, they never stay long.
Missionaries feel forever restless, for they know the pain and suffering the common folk endure due to their lack of spiritual guidance, and they want to alleviate it all. That is an impossible task, of course, but this desire prevents missionaries from staying very long in a place where their work is done. In fact, once they have lingered a week in a community cured of its major ills, they begin to ache for those suffering elsewhere and must move on.
Further, Citadel missionaries are viewed as a major threat by the Knights of Takhisis. Their tenaciousness and dedication to spreading the message of the Citadel directly threatens the Dark Knights´ efforts to control Ansalon and prepare the populace to control Ansalon and prepare the populace for the return of Takhisis. Whenever Dark Knights hear of a Missionary in lands they control, they devote their full atention to hunting down and killing him or her. For every week a missionary operates in Dark Knight-held lands –even if the hero is careful not to reveal his or her identity- the player must make a random draw from the Fate Deck. If the result has a black aura, someone has betrayed the hero to the Dark Knights, but a local warns the mystic of this in time to flee. (However, if the randomly drawn card is from the Suit of Dragons, the missionary receives no advance warning beyond a chance to notice the Knights as they thunder into the village upon their black steeds.)
Los clérigos no tienen, en general, más poder que cualquier ateo. Sin embargo, entre las gentes de Krynn algunas personas han desarrollado cierto control con la energía mágica que viene del interior de los seres vivos: El Misticismo. No todo antígüo clérigo la posee, y no todo el que la tiene, posee además fe y devoción. Al parecer, cierta intensidad en las emociones y fuerza de espíritu están asociadas a la posibilidad de desarrollar el Misticismo. Quien primero controló, según los registros, esta nueva forma de magia, fue la Heroína de la Lanza llamada Goldmoon. Ella ha conformado una organización en la isla de Schallsea, cerca de la Escalera de Plata, en la que se enseña de forma organizada el uso del Misticismo. Ella lo ha bautizado el "poder del corazón", porque está alimentado de la fortaleza del corazón de las personas, tanto de la emoción pura, como de la fe, según sus experiencias. La meditación se utiliza, junto con el apoyo de mantras, para encontrar la fuerza interior que permite, entre otras cosas, la curación. Al parecer este tipo de magia no es capaz de afectar las cosas que no están o han estado vivas. Puede afectarse a un ser humano o animal, pero no a una roca o un vaso de agua.
[<img[Majere - Arte de PsychaDurmont en www.dlnexus.com|http://www.dlnexus.com/gfx/art/17174.jpg]]
|!Valor de Habilidades|!Códigos de Habilidades|!Otros Req.|!Ventajas|!Desventajas|
|AG 6 min, EN 6 min, RE 5 min, PE 6 min, SP 7 min, PR 6 min|SP B min|Humano o medio-elfo; prohibición de las escuelas de espiritualismo y necromancia|Bono de Carta de Triunfo para combate desarmado y combate con armas livianas tanto de cuerpo-a-cuerpo muy livianas como de misil; el rol es difícil de adquirir durante el juego|
Name: MptwBlack
Background: #000
Foreground: #fff
PrimaryPale: #333
PrimaryLight: #555
PrimaryMid: #888
PrimaryDark: #aaa
SecondaryPale: #111
SecondaryLight: #222
SecondaryMid: #555
SecondaryDark: #888
TertiaryPale: #222
TertiaryLight: #666
TertiaryMid: #888
TertiaryDark: #aaa
Error: #300
This is in progress. Help appreciated.
Name: MptwBlue
Background: #fff
Foreground: #000
PrimaryPale: #cdf
PrimaryLight: #57c
PrimaryMid: #114
PrimaryDark: #012
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88
/***
|Name:|MptwConfigPlugin|
|Description:|Miscellaneous tweaks used by MPTW|
|Version:|1.0 ($Rev: 3646 $)|
|Date:|$Date: 2008-02-27 02:34:38 +1000 (Wed, 27 Feb 2008) $|
|Source:|http://mptw.tiddlyspot.com/#MptwConfigPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License:|http://mptw.tiddlyspot.com/#MptwConfigPlugin|
!!Note: instead of editing this you should put overrides in MptwUserConfigPlugin
***/
//{{{
var originalReadOnly = readOnly;
var originalShowBackstage = showBackstage;
config.options.chkHttpReadOnly = false; // means web visitors can experiment with your site by clicking edit
readOnly = false; // needed because the above doesn't work any more post 2.1 (??)
showBackstage = true; // show backstage for same reason
config.options.chkInsertTabs = true; // tab inserts a tab when editing a tiddler
config.views.wikified.defaultText = ""; // don't need message when a tiddler doesn't exist
config.views.editor.defaultText = ""; // don't need message when creating a new tiddler
config.options.chkSaveBackups = true; // do save backups
config.options.txtBackupFolder = 'twbackup'; // put backups in a backups folder
config.options.chkAutoSave = (window.location.protocol == "file:"); // do autosave if we're in local file
config.mptwVersion = "2.5.3";
config.macros.mptwVersion={handler:function(place){wikify(config.mptwVersion,place);}};
if (config.options.txtTheme == '')
config.options.txtTheme = 'MptwTheme';
// add to default GettingStarted
config.shadowTiddlers.GettingStarted += "\n\nSee also [[MPTW]].";
// add select theme and palette controls in default OptionsPanel
config.shadowTiddlers.OptionsPanel = config.shadowTiddlers.OptionsPanel.replace(/(\n\-\-\-\-\nAlso see AdvancedOptions)/, "{{select{<<selectTheme>>\n<<selectPalette>>}}}$1");
// these are used by ViewTemplate
config.mptwDateFormat = 'DD/MM/YY';
config.mptwJournalFormat = 'Journal DD/MM/YY';
//}}}
Name: MptwGreen
Background: #fff
Foreground: #000
PrimaryPale: #9b9
PrimaryLight: #385
PrimaryMid: #031
PrimaryDark: #020
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88
Name: MptwRed
Background: #fff
Foreground: #000
PrimaryPale: #eaa
PrimaryLight: #c55
PrimaryMid: #711
PrimaryDark: #500
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88
|Name|MptwRounded|
|Description|Mptw Theme with some rounded corners (Firefox only)|
|ViewTemplate|MptwTheme##ViewTemplate|
|EditTemplate|MptwTheme##EditTemplate|
|PageTemplate|MptwTheme##PageTemplate|
|StyleSheet|##StyleSheet|
!StyleSheet
/*{{{*/
[[MptwTheme##StyleSheet]]
.tiddler,
.sliderPanel,
.button,
.tiddlyLink,
.tabContents
{ -moz-border-radius: 1em; }
.tab {
-moz-border-radius-topleft: 0.5em;
-moz-border-radius-topright: 0.5em;
}
#topMenu {
-moz-border-radius-bottomleft: 2em;
-moz-border-radius-bottomright: 2em;
}
/*}}}*/
Name: MptwSmoke
Background: #fff
Foreground: #000
PrimaryPale: #aaa
PrimaryLight: #777
PrimaryMid: #111
PrimaryDark: #000
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88
|Name|MptwStandard|
|Description|Mptw Theme with the default TiddlyWiki PageLayout and Styles|
|ViewTemplate|MptwTheme##ViewTemplate|
|EditTemplate|MptwTheme##EditTemplate|
Name: MptwTeal
Background: #fff
Foreground: #000
PrimaryPale: #B5D1DF
PrimaryLight: #618FA9
PrimaryMid: #1a3844
PrimaryDark: #000
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #f8f8f8
TertiaryLight: #bbb
TertiaryMid: #999
TertiaryDark: #888
Error: #f88
|Name|MptwTheme|
|Description|Mptw Theme including custom PageLayout|
|PageTemplate|##PageTemplate|
|ViewTemplate|##ViewTemplate|
|EditTemplate|##EditTemplate|
|StyleSheet|##StyleSheet|
http://mptw.tiddlyspot.com/#MptwTheme ($Rev: 1829 $)
!PageTemplate
<!--{{{-->
<div class='header' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>
<div class='headerShadow'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
<div class='headerForeground'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
</div>
<!-- horizontal MainMenu -->
<div id='topMenu' refresh='content' tiddler='MainMenu'></div>
<!-- original MainMenu menu -->
<!-- <div id='mainMenu' refresh='content' tiddler='MainMenu'></div> -->
<div id='sidebar'>
<div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>
<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>
</div>
<div id='displayArea'>
<div id='messageArea'></div>
<div id='tiddlerDisplay'></div>
</div>
<!--}}}-->
!ViewTemplate
<!--{{{-->
[[MptwTheme##ViewTemplateToolbar]]
<div class="tagglyTagged" macro="tags"></div>
<div class='titleContainer'>
<span class='title' macro='view title'></span>
<span macro="miniTag"></span>
</div>
<div class='subtitle'>
(updated <span macro='view modified date {{config.mptwDateFormat?config.mptwDateFormat:"MM/0DD/YY"}}'></span>
by <span macro='view modifier link'></span>)
<!--
(<span macro='message views.wikified.createdPrompt'></span>
<span macro='view created date {{config.mptwDateFormat?config.mptwDateFormat:"MM/0DD/YY"}}'></span>)
-->
</div>
<div macro="showWhen tiddler.tags.containsAny(['css','html','pre','systemConfig']) && !tiddler.text.match('{{'+'{')">
<div class='viewer'><pre macro='view text'></pre></div>
</div>
<div macro="else">
<div class='viewer' macro='view text wikified'></div>
</div>
<div class="tagglyTagging" macro="tagglyTagging"></div>
<!--}}}-->
!ViewTemplateToolbar
<!--{{{-->
<div class='toolbar'>
<span macro="showWhenTagged systemConfig">
<span macro="toggleTag systemConfigDisable . '[[disable|systemConfigDisable]]'"></span>
</span>
<span macro="showWhenTagged systemTheme"><span macro="applyTheme"></span></span>
<span macro="showWhenTagged systemPalette"><span macro="applyPalette"></span></span>
<span macro="showWhen tiddler.tags.contains('css') || tiddler.title == 'StyleSheet'"><span macro="refreshAll"></span></span>
<span style="padding:1em;"></span>
<span macro='toolbar closeTiddler closeOthers +editTiddler deleteTiddler > fields syncing permalink references jump'></span> <span macro='newHere label:"new here"'></span>
<span macro='newJournalHere {{config.mptwJournalFormat?config.mptwJournalFormat:"MM/0DD/YY"}}'></span>
</div>
<!--}}}-->
!EditTemplate
<!--{{{-->
<div class="toolbar" macro="toolbar +saveTiddler saveCloseTiddler closeOthers -cancelTiddler cancelCloseTiddler deleteTiddler"></div>
<div class="title" macro="view title"></div>
<div class="editLabel">Title</div><div class="editor" macro="edit title"></div>
<div macro='annotations'></div>
<div class="editLabel">Content</div><div class="editor" macro="edit text"></div>
<div class="editLabel">Tags</div><div class="editor" macro="edit tags"></div>
<div class="editorFooter"><span macro="message views.editor.tagPrompt"></span><span macro="tagChooser"></span></div>
<!--}}}-->
!StyleSheet
/*{{{*/
/* a contrasting background so I can see where one tiddler ends and the other begins */
body {
background: [[ColorPalette::TertiaryLight]];
}
/* sexy colours and font for the header */
.headerForeground {
color: [[ColorPalette::PrimaryPale]];
}
.headerShadow, .headerShadow a {
color: [[ColorPalette::PrimaryMid]];
}
/* separate the top menu parts */
.headerForeground, .headerShadow {
padding: 1em 1em 0;
}
.headerForeground, .headerShadow {
font-family: 'Trebuchet MS' sans-serif;
font-weight:bold;
}
.headerForeground .siteSubtitle {
color: [[ColorPalette::PrimaryLight]];
}
.headerShadow .siteSubtitle {
color: [[ColorPalette::PrimaryMid]];
}
/* make shadow go and down right instead of up and left */
.headerShadow {
left: 1px;
top: 1px;
}
/* prefer monospace for editing */
.editor textarea, .editor input {
font-family: 'Consolas' monospace;
background-color:[[ColorPalette::TertiaryPale]];
}
/* sexy tiddler titles */
.title {
font-size: 250%;
color: [[ColorPalette::PrimaryLight]];
font-family: 'Trebuchet MS' sans-serif;
}
/* more subtle tiddler subtitle */
.subtitle {
padding:0px;
margin:0px;
padding-left:1em;
font-size: 90%;
color: [[ColorPalette::TertiaryMid]];
}
.subtitle .tiddlyLink {
color: [[ColorPalette::TertiaryMid]];
}
/* a little bit of extra whitespace */
.viewer {
padding-bottom:3px;
}
/* don't want any background color for headings */
h1,h2,h3,h4,h5,h6 {
background-color: transparent;
color: [[ColorPalette::Foreground]];
}
/* give tiddlers 3d style border and explicit background */
.tiddler {
background: [[ColorPalette::Background]];
border-right: 2px [[ColorPalette::TertiaryMid]] solid;
border-bottom: 2px [[ColorPalette::TertiaryMid]] solid;
margin-bottom: 1em;
padding:1em 2em 2em 1.5em;
}
/* make options slider look nicer */
#sidebarOptions .sliderPanel {
border:solid 1px [[ColorPalette::PrimaryLight]];
}
/* the borders look wrong with the body background */
#sidebar .button {
border-style: none;
}
/* this means you can put line breaks in SidebarOptions for readability */
#sidebarOptions br {
display:none;
}
/* undo the above in OptionsPanel */
#sidebarOptions .sliderPanel br {
display:inline;
}
/* horizontal main menu stuff */
#displayArea {
margin: 1em 15.7em 0em 1em; /* use the freed up space */
}
#topMenu br {
display: none;
}
#topMenu {
background: [[ColorPalette::PrimaryMid]];
color:[[ColorPalette::PrimaryPale]];
}
#topMenu {
padding:2px;
}
#topMenu .button, #topMenu .tiddlyLink, #topMenu a {
margin-left: 0.5em;
margin-right: 0.5em;
padding-left: 3px;
padding-right: 3px;
color: [[ColorPalette::PrimaryPale]];
font-size: 115%;
}
#topMenu .button:hover, #topMenu .tiddlyLink:hover {
background: [[ColorPalette::PrimaryDark]];
}
/* make 2.2 act like 2.1 with the invisible buttons */
.toolbar {
visibility:hidden;
}
.selected .toolbar {
visibility:visible;
}
/* experimental. this is a little borked in IE7 with the button
* borders but worth it I think for the extra screen realestate */
.toolbar { float:right; }
/* fix for TaggerPlugin. from sb56637. improved by FND */
.popup li .tagger a {
display:inline;
}
/* makes theme selector look a little better */
#sidebarOptions .sliderPanel .select .button {
padding:0.5em;
display:block;
}
#sidebarOptions .sliderPanel .select br {
display:none;
}
/* make it print a little cleaner */
@media print {
#topMenu {
display: none ! important;
}
/* not sure if we need all the importants */
.tiddler {
border-style: none ! important;
margin:0px ! important;
padding:0px ! important;
padding-bottom:2em ! important;
}
.tagglyTagging .button, .tagglyTagging .hidebutton {
display: none ! important;
}
.headerShadow {
visibility: hidden ! important;
}
.tagglyTagged .quickopentag, .tagged .quickopentag {
border-style: none ! important;
}
.quickopentag a.button, .miniTag {
display: none ! important;
}
}
/* get user styles specified in StyleSheet */
[[StyleSheet]]
/*}}}*/
|Name|MptwTrim|
|Description|Mptw Theme with a reduced header to increase useful space|
|ViewTemplate|MptwTheme##ViewTemplate|
|EditTemplate|MptwTheme##EditTemplate|
|StyleSheet|MptwTheme##StyleSheet|
|PageTemplate|##PageTemplate|
!PageTemplate
<!--{{{-->
<!-- horizontal MainMenu -->
<div id='topMenu' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>
<span refresh='content' tiddler='SiteTitle' style="padding-left:1em;font-weight:bold;"></span>:
<span refresh='content' tiddler='MainMenu'></span>
</div>
<div id='sidebar'>
<div id='sidebarOptions'>
<div refresh='content' tiddler='SideBarOptions'></div>
<div style="margin-left:0.1em;"
macro='slider chkTabSliderPanel SideBarTabs {{"tabs \u00bb"}} "Show Timeline, All, Tags, etc"'></div>
</div>
</div>
<div id='displayArea'>
<div id='messageArea'></div>
<div id='tiddlerDisplay'></div>
</div>
For upgrading. See [[ImportTiddlers]].
URL: http://mptw.tiddlyspot.com/upgrade.html
/***
|Description:|A place to put your config tweaks so they aren't overwritten when you upgrade MPTW|
See http://www.tiddlywiki.org/wiki/Configuration_Options for other options you can set. In some cases where there are clashes with other plugins it might help to rename this to zzMptwUserConfigPlugin so it gets executed last.
***/
//{{{
// example: set your preferred date format
//config.mptwDateFormat = 'MM/0DD/YY';
//config.mptwJournalFormat = 'Journal MM/0DD/YY';
// example: set the theme you want to start with
//config.options.txtTheme = 'MptwRoundTheme';
// example: switch off autosave, switch on backups and set a backup folder
//config.options.chkSaveBackups = true;
//config.options.chkAutoSave = false;
//config.options.txtBackupFolder = 'backups';
// uncomment to disable 'new means new' functionality for the new journal macro
//config.newMeansNewForJournalsToo = false;
//}}}
Shapechanger Hero Secrets
Suit Animal Card Value Hero Secret
Shields Crocodile 1 Haunted
Arrows Panther 2 Second Sight
Helms Grizzly Bear 3 Shared Body
Swords Leopard 4-5 Illegitimate child
Moons Giant Owl 6-7 Traitor
Orbs Dolphin 8 Enemy
Hearts Wolf 9 Shapechanger
Crowns Kingfisher 10 Predestined
Dragons Giant Lizard
In many of Ansalon's cultures, those with mystical talent are trained to become members of certain groups. Dwarf elders teach talented youngsters the ways of earth magic, barbarian shamans show promising youths how to learn from the spirits, and Solamnic Knights with a talent for mysticism seek knowledge from-the Orders of the Sword and the Rose to develop those talents. Independent mystics, on the other hand, learn to make use of their natural talents either on their own or from a mentor not associated with any mystical group.
Often, an independent mystic dis-covers his skills through some signifi-cant event in his life or through some minor trait that becomes apparent only as he grows older. Of course, some people never choose to explore these strange traits, but those who do often discover they are capable of much more than they knew. For instance:
*The hero always seems to sense dan-ger right before some ill befalls him or those around him, but he may never have realized he had an affin-ity for the sphere of sensitivity until a group of goblin marauders attacked his village.
*Another hero-a natural animist-might find that a certain bad-tempered war horse, which already bit three hostlers, always becomes docile around him.
*Or perhaps a hero decided to exper-iment with the art of healing after seeing that he recovered from injury faster than others around him.
Ansalon's organized mystic groups (see Chapter Two) fear what a lack of training may bring out in these independents, so they often try to per-suade them to refine their talents with some sort of instruction. However, independent mystics often believe that only through individual study can they fully explore their own magical abilities.
!Role-Playing:
By circumstance or design, the inde-pendent mystic has remained unat-tached to any mystical group. As a result, he possesses a greater freedom of action than do mystics of the Citadel, the Order of the Skull, or other organizations. They follow only their own interests and passions, although they are not necessarily self-centered. Many find their motivation in selfless pursuits, while others act out of petty cruelty. If there is one underlying similarity among these mystics, it is their individualism. Many of them wear their "me against the world" outlook as a badge of honor.
Of course, some independent mys-tics may decide later to join a mystic organization. Others may once have belonged to such a group but, for some reason, chose to distance themselves from their former comrades: A recluse who once served in the Knights of the Skull is as likely to be an independent mystic as a tavern owner who years ago arrived at the Citadel as a refugee and, while there, studied mysticism under its masters.
!Requirements:
Heroes of any race may play this role, as long as they have a score of at least 3 and a code of at least "B" in Spirit. There are no particular sphere require-ments for independent mystics, but they should not belong to any mystic organization.
!Advantages:
An independent mystic with a Spirit code of "A" enjoys an automatic trump bonus for magical actions that involve his "specialty" sphere-the first mystic sphere the hero ever learned. Those independents with a "B" code cannot gain a specialty until they first improve their knowledge of mysticism.
Independent mystics are not restricted in their magical education by the constraints of any group. Their lack of sphere requirements or prohibitions gives them an excellent chance to dis-cover new combinations of magical effects or new aspects of the magic of the Fifth Age. Furthermore, independent mystics are free to learn sorcery also and use any type of weapon or combat tactic they choose. This role is best suited, therefore, to those who pre-fer as few constraints on their educa-tion as possible.
Heroes can adopt this role during play, whether they previously played a mystic role or have only now awakened to their latent powers.
!Disadvantages:
Many people feel naturally suspicious of spellcasters but, in the case of mys-tics associated with organizations like the Knights of Solamnia or the Citadel of Light, the group's reputation affords them at least a little trust. Because independent mystics have no such affil-iations, though, people seem more wary of them.
When an independent mystic attempts a Presence action involving someone who does not know him, he receives a -3 action penalty (assuming the stranger knows he possesses magical powers). Of course, an unscrupulous mystic might claim affiliation with a mystic organization, but if the lie is ever discovered the action penalty doubles (to -6). Individuals may reduce or negate either penalty through role-play-ing. The penalty does not apply to Pres-ence actions to resist mystic magic.
[>img[Arte de Lindsay Archer en www.dlnexus.com|http://www.dlnexus.com/gfx/art/20598.jpg]]Ability Scores Ability Codes
SP 4 min SP B min
Other Requirements: Wealth 5 max; Nature 6 max; demeanor 6 max.
Advantages
Trump bonus for mysticism against Dark Knights and for mystic defense against Solamnics; code improvement bonus; apprentices; can acquire role during play.
Disadvantages
Death if captured by a Dark Knight; extra brutal treatment while a prisoner of Skull Knights; apprentices.
[>img[Arte de Jennifer Meyer en www.dlnexus.com|http://www.dlnexus.com/gfx/art/20540.jpg]]
History may show that Goldmoon's greatest contribution to Krynn was her discovery in 5sc of her inner power to heal and her subsequent decision to teach others this power. Thus was founded on the island of Schailsea the Citadel of Light.
Since then, she and Jasper, the hill dwarf she healed, have expanded the Citadel's teachings. Many people from all over Ansalon have sought out the Citadel to learn and understand the secrets of the heart. Some of them are refugees forced from their homes by the ravages of the dragons, while others come to learn of this strange power that Goldmoon has discovered.
On the isle of Schallsea live mystics of all levels of training, from novices to masters. These folk study nearly every sphere of mysticism, but they are renowned for their healing skills, both mundane and magical. It is Gold-moon's desire that the Citadel's legacy to the world be the art of healing. Many Citadel mystics also train in sen-sitivity and mentalism, both of which supplement their healing skills.
However, Goldmoon and the other masters of the Citadel do not allow their followers to study necromancy, and learning this art from an outside source is grounds for immediate dismissal. The Citadel does teach spiritualism, but only to certain advanced students whom the masters feel have the wisdom to under-stand the inherent dangers of dealing with spirits. Students who learn this art are forbidden to create any of the intangible, spectral undead-wraiths, ghosts, specters, and other such creatures.
!Role-Playing:
Mystics of the Citadel of Light use their powers for the good of those around them, be they poor refugees or proud knights. They have learned from Gold-moon and the other masters the power to heal others of their injuries and illnesses. Their mundane medical skills enable them to help others even when their magical powers are exhausted. Whether they remain at the Citadel and aid those who have sustained terrible injuries in their flight from the devasta-tion of their homes or go out among the free peoples of the world and assist them with their skills, they are valuable friends to those around them.
Though they prefer to resolve differ-ences peacefully, Citadel mystics are more than capable of overcoming a foe in battle if threatened. These heroes tend to use weapons that disarm or dis-able an opponent rather than injure him, but they are not required to do so.
Jasper Fireforge, a Hero of the Heart, typifies the Citadel mystic.
!Requirements:
Mystics of the Citadel of Light may be of any race. Goldmoon welcomes any-one of good intentions who comes to the Citadel to learn. She interviews applicants personally, reading their auras (using the sensitivity sphere) to determine whether their spirits are ready for training and whether they have the right sort of moral character to become a Citadel mystic.
To adopt this role, a hero must have a code of "B" or better and a score of at least 4 in Spirit. As mystics of the Citadel are not particularly eager to pursue combat-although they can defend themselves capably-they must have a Dexterity and Strength code of "C" or lower as well as a maximum Agility and Endurance code of "B." If a player's initial card selection during hero creation would result in higher Physical codes than allowed, the player may reduce them voluntarily; however, he may not raise other codes to make up fur the reduction.
All Citadel mystics are expected to learn the sphere of healing. They can study other spheres as well, except for necromancy. Any hero or character that studies necromancy will be dis-missed from the Citadel upon discov-ery: Goldmoon has remained adamant on this point.
Any person wishing to study at the Citadel must follow a high moral stan-dard. Therefore, players may not assign Dragons cards or Hearts cards with a black aura to the nature of a Citadel mystic during hero creation.
!Advantages:
Citadel mystics are known for their compassion and their support for the rights of the individual. Once they have identified themselves as followers of Goldmoon, they gain a trump bonus to any Presence action involving refugees, prisoners, or downtrodden peasants.
Additionally, since the Citadel enjoys respect among an increasing number of rulers and lords in the free realms of Ansalon, Citadel mystics often can gain aid from local rulers, if they seek them out. To take advantage of this benefit, the mystic's player turns a card from the Pate Deck.
*If the card's aura is white or red, the lord feels favorably disposed toward the mystic and his party and offers what aid he can.
*A black aura means the lord is neu-trally disposed toward the Citadel and its mystics, but the heroes have an opportunity to convince him of their good intentions. (Role-playing and perhaps another random draw dictates whether the heroes receive the aid they sought.)
*Drawing a Dragons card reveals that the lord opposes the Citadel. The Narrator's story dictates whether this ruler simply turns the heroes away, dispatches men-of-arms against them, or pretends to be friendly while sending word to their enemies
Heroes may adopt this role at any time in their career, assuming they hav the requisite scores and codes.
!Disadvantages:
The primary disadvantage for followers of the Citadel of Light is the restriction on what spheres they are allowed to learn. No follower may practice necro-mancy under any circumstances, and any who wish to study spiritualism must first gain the permission of Gold-moon and the Citadel's mystic masters.
Goldmoon does not forbid those who have studied necromancy under other mystics to join her organization, although she forbids them from ever using that magic while representing the Citadel. (In effect, such mystics retain the understanding of the necromancy sphere but may not use it without risk-ing censure or expulsion.)
Dwarf Earth Mystic
Abitlity Scores Ability Codes
AG 8 max RE B
DX 8 max SP B min
EN 6 min
ST 6 min
RE 5 min
SP 5 min
Other Requirements: Dwarves only; geomancy school and sensitivity sphere required.
Advantages
Trump bonus to resist poison or sorcery and for earth magic and earth-related PR actions; can adopt role during play.
Disadvantages
No trump bonus for certain personality-related actions, using nonearth magic, or any PR actions.
//~Mystic-Sorcerer//
|!Valor de Habilidades|!Códigos de Habilidades|!Otros Req.|!Ventajas|!Desventajas|
|Razonamiento 6 min, Espíritu 6 min|Razonamiento B min, Espíritu B min|Ninguno|Aquellos con A en Razonamiento y Espíritu pueden combinar esferas ocn escuelas; puede adoptarse el rol durante el juego|Ninguna habilidad física debe tener código mayor a C (puede bajarse el código voluntariamente)|
Narrators should keep in mind a few additional concepts as players attempt actions in the game.
Mishaps
One suit of the Fate Deck has not been discussed yet: the Suit of Dragons. Dragons represent misfortune and can have dire effects on heroes' actions. If a hero plays a card from the Suit of Dragons and the action fails, some sort of mishap has occurred, such as an injury (loss of a card) or just embarrassment. It is up to the Narrator to interpret the situation and decide exactly what the mishap is and how bad the situation becomes.
Ability Codes
In many ways, heroes' ability codes are more important than their scores. A hero may be strong as an ox, but without proper training he or she can use only the most basic of weapons. Narrators should make sure that heroes do not consistently perform actions that are beyond their capabilities. The general relationship between code, capability, and level of training in skills related to the ability is as follows:
A (expert): Fully trained in associated skills.
B (advanced): Trained in most associated skills.
C (journeyman): Trained in common associated skills.
D (beginner): Trained in basic associated skills.
X (novice): No training in associated skills.
Other Tips
Finally, here are a few things every Narrator should keep in mind during a Saga roleplaying game:
Only heroes attempt actions! No one ever need play cards for a character.
Be colorful with your descriptions. You are painting the scene for the players, describing all the things their senses would tell them. The more artfully you do this, the more everyone will enjoy the game.
You and the other players are working together to create a story; you are not adversaries (even though the heroes and some characters might be). When the heroes succeed, you do too!
Saga roleplaying is supposed to be fun! These rules are guidelines only, so never let strict adherence to them spoil your game!
Copyright ©1996-2001 James O'Rance.
!¿Cómo navegar por SAGApedia?
*Haga click en los hipervínculos (links) o partes del menú superior progresivamente.
*Cada vez que abra un nuevo micro-contenido luego de hacer click, el micro-contenido se abrirá ahondando en detalles. El micro-contenido anterior no desaparecerá de su pantalla sino que se mantendrá abierto.
*No es de utilidad hacer uso del botón "Atrás" o "Back" del navegador de internet. En su lugar, debe hacer uso de los controles del micro-contenido (texto gris que aparece a la derecha y arriba en cada micro-contenido al pasar el ratón por esa esquina). Las opciones por defecto son:
**{{{close}}}: cerrará el micro-contenido al cuál pertenece.
**{{{close others}}}: cerrará todos los micro-contenidos excepto ese al cuál pertenece.
**{{{edit}}}: activará un modo de edición del contenido del tiddler. Para quien consulta SAGApedia no es de utilidad, pues no se pueden guardar los cambios.
**{{{delete}}}: borra el micro-contenido, pero sin la permisología correcta, no tiene efecto debido a que no se pueden guardar los cambios.
**{{{more}}}: hace disponibles [[otros controles]] del micro-contenido.
**{{{new here}}}: hace posible crear un nuevo micro-contenido. No es de utilidad para quién consulta la SAGApedia.
**{{{new journal}}}: hace posible crear un nuevo micro-contenido con título igual a la fecha del día de creación. No es de utilidad para quién consulta la SAGApedia.
*Si hace doble-click, intencionalmente o no, sobre el contenido de un micro-contenido (tiddler), este cambiará a modo de edición. Sin embargo, si usted no está autorizado, no podrá modificar permanentemente ningún micro-contenido. Para salir de modo edición, use los controles del micro-contenido:
**{{{done/close}}} o {{{cancel/close}}}: para salir del modo de edición y cerrar el micro-contenido. Si eligió {{{cancel/close}}}, se descartará cualquier cambio realizado en la edición.
**{{{close others}}}: en esta implementación este control //no tendrá efectos visibles// para el usuario.
**{{{done}}}: para salir del modo de edición, manteniendo el micro-contenido en pantalla.
/***
|Name:|NewHerePlugin|
|Description:|Creates the new here and new journal macros|
|Version:|3.0 ($Rev: 3861 $)|
|Date:|$Date: 2008-03-08 10:53:09 +1000 (Sat, 08 Mar 2008) $|
|Source:|http://mptw.tiddlyspot.com/#NewHerePlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License|http://mptw.tiddlyspot.com/#TheBSDLicense|
***/
//{{{
merge(config.macros, {
newHere: {
handler: function(place,macroName,params,wikifier,paramString,tiddler) {
wikify("<<newTiddler "+paramString+" tag:[["+tiddler.title+"]]>>",place,null,tiddler);
}
},
newJournalHere: {
handler: function(place,macroName,params,wikifier,paramString,tiddler) {
wikify("<<newJournal "+paramString+" tag:[["+tiddler.title+"]]>>",place,null,tiddler);
}
}
});
//}}}
/***
|Name:|NewMeansNewPlugin|
|Description:|If 'New Tiddler' already exists then create 'New Tiddler (1)' and so on|
|Version:|1.1.1 ($Rev: 2263 $)|
|Date:|$Date: 2007-06-13 04:22:32 +1000 (Wed, 13 Jun 2007) $|
|Source:|http://mptw.tiddlyspot.com/empty.html#NewMeansNewPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License|http://mptw.tiddlyspot.com/#TheBSDLicense|
!!Note: I think this should be in the core
***/
//{{{
// change this or set config.newMeansNewForJournalsToo it in MptwUuserConfigPlugin
if (config.newMeansNewForJournalsToo == undefined) config.newMeansNewForJournalsToo = true;
String.prototype.getNextFreeName = function() {
var numberRegExp = / \(([0-9]+)\)$/;
var match = numberRegExp.exec(this);
if (match) {
var num = parseInt(match[1]) + 1;
return this.replace(numberRegExp," ("+num+")");
}
else {
return this + " (1)";
}
}
config.macros.newTiddler.checkForUnsaved = function(newName) {
var r = false;
story.forEachTiddler(function(title,element) {
if (title == newName)
r = true;
});
return r;
}
config.macros.newTiddler.getName = function(newName) {
while (store.getTiddler(newName) || config.macros.newTiddler.checkForUnsaved(newName))
newName = newName.getNextFreeName();
return newName;
}
config.macros.newTiddler.onClickNewTiddler = function()
{
var title = this.getAttribute("newTitle");
if(this.getAttribute("isJournal") == "true") {
title = new Date().formatString(title.trim());
}
// ---- these three lines should be the only difference between this and the core onClickNewTiddler
if (config.newMeansNewForJournalsToo || this.getAttribute("isJournal") != "true")
title = config.macros.newTiddler.getName(title);
var params = this.getAttribute("params");
var tags = params ? params.split("|") : [];
var focus = this.getAttribute("newFocus");
var template = this.getAttribute("newTemplate");
var customFields = this.getAttribute("customFields");
if(!customFields && !store.isShadowTiddler(title))
customFields = String.encodeHashMap(config.defaultCustomFields);
story.displayTiddler(null,title,template,false,null,null);
var tiddlerElem = story.getTiddler(title);
if(customFields)
story.addCustomFields(tiddlerElem,customFields);
var text = this.getAttribute("newText");
if(typeof text == "string")
story.getTiddlerField(title,"text").value = text.format([title]);
for(var t=0;t<tags.length;t++)
story.setTiddlerTag(title,tags[t],+1);
story.focusTiddler(title,focus);
return false;
};
//}}}
|!Valores de Habilidades |!Códigos de Habilidades |!Otros Requerimientos |!Ventajas |!Desventajas|
|Cualquiera.| Cualquiera. | Riqueza 6 máximo| Simpatizantes; Carta de Triunfo para imitar antígüo estatus social; puede recobrar su estatus.| Encuentra un enemigo una vez por aventura; rol difícil de adquirir durante el juego.|
<<tiddler TspotOptions>>These InterfaceOptions for customising TiddlyWiki are saved in your browser
Your username for signing your edits. Write it as a WikiWord (eg JoeBloggs)
<<option txtUserName>>
<<option chkSaveBackups>> SaveBackups
<<option chkAutoSave>> AutoSave
<<option chkRegExpSearch>> RegExpSearch
<<option chkCaseSensitiveSearch>> CaseSensitiveSearch
<<option chkAnimate>> EnableAnimations
{{select{<<selectTheme>>
<<selectPalette>>}}}
----
Also see [[AdvancedOptions]]
The back of the Character Card tells more about a hero. Demeanor defines how the hero acts outwardly, and nature describes what he or she is really like deep down. Reputation measures how well known the hero is (and determines the size of the player's hand), while social status indicates the hero's economic class (and regulates how much money he or she has to spend). The weapon and armor entries list the hero's favored gear. The paragraphs in the lower half of the card describe the hero's background and goals. They also mention any special abilities he or she may have (such as magical aptitude or acute senses).
Paladins are Knights of Solamnia that are also clerics of Paladine. When the Knights of Solamnia discovered that the populace was losing its faith, the Order decided that they needed missionaries. They sent a select few to the Citadel of Light, where they studied mysticism. They are wanderers, spreading the faith of the Gods of Good throughout Ansalon.
!Role Playing:
Paladins follow the Measure, as do the other Solamnic knights, a set of rules that defines how to put the Oath into effect in one's daily life. The Paladin doesn't owe forty to sixty days of direct service to the Order each year. In fact, Paladins don't even seem to be in the Order, even though they are members.
Paladins aren't wildly dedicated to their religion, and they don't force their religion upon others. They are strict and unyielding when it comes to the Laws of Paladine, the Oath, and the Measure. they teach those willing to learn about the departed Gods of Good, and help those in need. Paladins commit their lives to justice, compassion, and to spreading the faith of the Gods of Good throughout Ansalon.
Paladins are usually loners, and move nomadically; much like an Adventurous Warrior. Most seek out crimes, and set out to right them. Often, they act as judge, jury, and executioner. Paladins can expect at least a grudging welcome wherever they go, with the exception of areas controlled by the Knights of Takhisis or Dragon Overlords. In all other regions, the common folk recognize Paladins as their guardians and in some cases as figures of authority.
!Requirements:
Because of their strenuous life, a Paladin must have Strength and Endurance scores of at least 7. Paladins need a strong faith, so he must have a Spirit score of at least 7 as well. Because peasants see a Paladin as a figure of great importance, a Paladin must have a Presence score of at least 6. A Paladin is trained how to fight from his childhood. Therefore, a Paladin must have Strength and Endurance codes of "A". Paladins have studied at the Citadel of Light for a long time. Therefore, a Paladin must have a Spirit code of "A". Only civilized humans and half-elves can play paladins. Players may not select a card with a value greater than 4 for their nature or demeanor. Paladins only have what they carry, so they start out with a maximum wealth score of 4.
!Advantages:
Paladins excel at swordsmanship. To reflect this, Paladins get a Trump bonus whenever they use a longsword, broad sword, great sword, or two-handed sword. Because of their devout faith, Paladins can resist magic spells better than normal people. Paladins get a +3 bonus to resist magic. Because of their strong authority, Paladins gain an automatic Trump bonus to all Presence actions when dealing with all characters except those of Royalty wealth. This includes giving orders, raising morale, and detecting lies.
!Disadvantages:
Paladins disdain missile weapons, and will not recieve a Trump bonus when using a missile weapon, regardless of the suit. Paladins also cannot draw from Solamnic funds. Paladins can never learn sorcery. A Paladin never likes to retreat from or refuse combat with Evil forces. However, if the cause is foolish or useless, they must attempt a daunting Abandon/Refuse Fight action:
Abandon/Refuse Fight
Difficulty Challenging
Action ability Reason
Opposition ability Presence (only INT foes)
Comments: This action always becomes easy when an enemy of equal or greater Strength (or Physique) outnumbers the Knight and his group at least three to one. If a trusted ally urges the hero to refuse or abandon a fight, the ally adds his Presence score to the Knight's Reason score for this action. A higher-ranking Knight (one with a greater reputation or official office) can order the hero away from a fight, but the superior must succeed in this action himself before he can issue the order. As a Knight finds no dishonor in living to fight another day, he may add his foe's Strength (or Physique) score to his Reason score for this action.
Mishap: The Knight's foe gets a free counterattack outside the normal combat sequence.
If Paladins do something that contradicts the Laws of Paladine, or the Oath and the Measure, then their Presence score drops by 1 point. They must make penance by going on a near-impossible quest. They must complete:
* Three acts of compassion
* Restoring something that was lost
* Change the life a someone by showing him the Laws of Paladine
In the Knighthood, Paladins have the rankings of a Knight of the Sword.
[[Palanthas]] está regida por los [[Caballeros de Takhisis]], quienes a su vez son comandados por el Señor Dragon [[Khellendros]].
La [[Torre de Alta Hechicería de Palanthas]] ha desaparecido dejando un misterioso disco de obsdiana en medio del [[Robledal de Shoikan]]. Se ha dicho que la torre fue desvanecida por un mago túnica negra que llevaba una vara similar a la [[Vara de Magius]], y que quien logra ver en el disco, ve una imágen de la torre, congelada en el tiempo. Con la desaparición de la torre, la [[Torre de Alta Hechicería de Wayreth]] queda como la última de las 5 torres originales de la Alta Hechicería.
El ala de la [[Biblioteca de Palanthas]] que contenía todos los tomos escritos por [[Astinus de Palanthas]] desde el orígen de los tiempos, desapareció al final de la [[Guerra de Chaos]], junto con el propio [[Astinus de Palanthas]].
‘Staunch Supporter’
Ability Scores Ability Codes Other Req.’s Advantages Disadvantages
Re 4 min. Any. Wealth of Trump bonus to deal with Challenging Re action to
Sp 4 min. 7 min. lord’s servants and convince others of true
minions. sympathies; can adopt
role during play only
under a new regime.
/***
|''Name:''|PasswordOptionPlugin|
|''Description:''|Extends TiddlyWiki options with non encrypted password option.|
|''Version:''|1.0.2|
|''Date:''|Apr 19, 2007|
|''Source:''|http://tiddlywiki.bidix.info/#PasswordOptionPlugin|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0 (Beta 5)|
***/
//{{{
version.extensions.PasswordOptionPlugin = {
major: 1, minor: 0, revision: 2,
date: new Date("Apr 19, 2007"),
source: 'http://tiddlywiki.bidix.info/#PasswordOptionPlugin',
author: 'BidiX (BidiX (at) bidix (dot) info',
license: '[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D]]',
coreVersion: '2.2.0 (Beta 5)'
};
config.macros.option.passwordCheckboxLabel = "Save this password on this computer";
config.macros.option.passwordInputType = "password"; // password | text
setStylesheet(".pasOptionInput {width: 11em;}\n","passwordInputTypeStyle");
merge(config.macros.option.types, {
'pas': {
elementType: "input",
valueField: "value",
eventName: "onkeyup",
className: "pasOptionInput",
typeValue: config.macros.option.passwordInputType,
create: function(place,type,opt,className,desc) {
// password field
config.macros.option.genericCreate(place,'pas',opt,className,desc);
// checkbox linked with this password "save this password on this computer"
config.macros.option.genericCreate(place,'chk','chk'+opt,className,desc);
// text savePasswordCheckboxLabel
place.appendChild(document.createTextNode(config.macros.option.passwordCheckboxLabel));
},
onChange: config.macros.option.genericOnChange
}
});
merge(config.optionHandlers['chk'], {
get: function(name) {
// is there an option linked with this chk ?
var opt = name.substr(3);
if (config.options[opt])
saveOptionCookie(opt);
return config.options[name] ? "true" : "false";
}
});
merge(config.optionHandlers, {
'pas': {
get: function(name) {
if (config.options["chk"+name]) {
return encodeCookie(config.options[name].toString());
} else {
return "";
}
},
set: function(name,value) {config.options[name] = decodeCookie(value);}
}
});
// need to reload options to load passwordOptions
loadOptionsCookie();
/*
if (!config.options['pasPassword'])
config.options['pasPassword'] = '';
merge(config.optionsDesc,{
pasPassword: "Test password"
});
*/
//}}}
Daggers (STR/DEX)
Armor optimization (END)
Axes (STR)
Clubs (STR)
Flails (STR)
Hammers/Maces (STR)
Hand to Hand (STR)
Parrying/Resisting (END)
Pole Arms/Spears/Lances (STR)
Staves (STR)
Swords (STR)
Profession (DEX/REA)
Sailing (REA/DEX/AGI)
Administration (REA)
Alchemy (REA)
Concealment (PER)
Cryptography (REA)
Disguise (PER)
Expert (REA)
Gambling (REA)
General Knowledge (REA)
History (REA)
Intrigue (REA)
Inventor (REA)
Investigation (REA)
Language (REA)
Law (REA)
Lip Reading (REA)
Local Expert (REA)
Lore (REA)
Noble Lore (Heraldry) (REA)
Perception (REA)
Politics (REA)
Siegecraft/Siege Weapons (REA)
Streetwise (REA/PRE)
Tactics/Strategy (REA)
Wilderness Lore (REA)
Acrobatics (DEX)
Archery (DEX)
Artisan Skills (DEX)
Artist (DEX)
Athletics (AGI)
Bind Wounds (DEX)
Contortionist (AGI)
Crossbows (DEX)
Dance (AGI/PRE)
Daggers (STR/DEX)
Dodge (Agi)
Fletching (DEX)
Forgery (DEX)
Horsemanship (AGI)
Lockpicking (DEX)
Profession (DEX/REA)
Sailing (REA/DEX/AGI)
Throwing (DEX)
Ventriloquiest (DEX/PRE)
Wagon Driving (DEX)
Whips (DEX)
Throwing (includes Slings) (DEX)
Stealth (AGI)
Sleight of Hand (AGI/DEX)
Smithing (DEX)
Dance (AGI/PRE)
Ventriloquiest (DEX/PRE)
Animal Handler (PRE)
Acting (PRE)
Concentration (SPI)
Courtier (PRE)
Diplomacy (PRE)
Interaction (PRE)
Interrogation (PRE)
Leadership (PRE)
Meditation (SPI)
Merchant Skills (PRE)
Mimicry (PRE)
Streetwise (REA/PRE)
Teaching (PRE)
Ability Scores Ability Codes Other Req.’s Advantages Disadvantages
All must be Four must be Wealth 7 min. Others let information Lose advantage if hero’s
5 min. “B” min. slip. secret gets out; only
newcomers can acquire
role during play.
Street Urchin
Ability Scores Ability Codes Other Req.’s Advantages Disadvantages
Any. Must explain Wealth 3 max. Can find hideout in Pr actions to deal with
any code beyond homecity; network known foes must be
“C”. of friends; eavesdropping daunting or higher; cannot
Trump bonus to steal. acquire role during play.
Ambos, la habilidad y la "pinta" están asociadas a cierto tipo de acciones:
#''Escudos / Agilidad'': Acrobacias / esquivar / equilibrio
#''Flechas / Destreza'': Coordinación ojo mano / manipulación fina / combate con armas de misil
#''Yelmos / Resistencia'': Resistencia / Inmunidad a enfermedades / defensa en combate cuerpo a cuerpo
#''Espadas / Fuerza'': Fuerza Bruta / ataque en combates cuerpo a cuerpo
#''Lunas / Razonamiento'': tareas intelectuales / memoria / hechicería
#''Orbes / Percepción'': Percepción / Intuición / resistir magia de hechicería
#''Corazones / Espíritu'': Fuerza de Voluntad / magia mística / Fuerza emocional / Empatía
#''Coronas / Presencia'': Liderazgo / Autoestima / resistencia a magia mística
Si se usan para las acciones correspondientes, se obtiene una [[Carta de Triunfo]].
Adicionalmente, está la [[pinta|Pinta de las cartas]] de los dragones:
''Dragones/Caos'': Representan el caos reinante debido a la ida de los dioses. Si una acción es fallada habiendo sido una de estas cartas la última en colocarse sobre la mesa, el fallo es no es normal. Es una [[desgracia|Desgracia]].
''Resolución de Acciones por Lectura de Pinta''
En apariencia, toda acción implica una lectura de Pinta, porque esta determina si hay o no Carta de Triunfo, o si hay posibilidad de fallo catastrófico. Sin embargo, un narrador puede querer, en ciertas circunstancias, resolver el resultado de una situación o acción, de manera completamente aleatoria, leyendo la pinta de una carta sacada al azar. Por ejemplo, si en una cueva hay enemigos y el héroe no puede apuntar por no haber luz, pudiera determinarse con una carta sacada al azar, que una flecha hirió a alguien, si es de la pinta de las flechas. Esto sería más difícil que acertar, haciendo una lectura aleatoria de aura. Alternativamente pudieran mezclarse lecturas de pinta y aura: si en la cueva hay aliados y enemigos, puede determinarse que la flecha hiere a alguien, según la pinta, y determinarse si era amigo o enemigo, basándose en el aura.
''Acciones en situación de desastre''
A veces algo horrible pasa a los héroes. Por ejemplo, el tunel por el que caminan colapsa, o se encuentran en el rango de una explosión. En los casos en que la sobrevivencia es más un asunto de suerte que de habilidad, el narrador puede voltear una carta del mazo, y solicitar a los jugadores que jueguen una carta con la misma pinta. Quienes lo logran, salen ilesos. La gravedad de las consecuencias, en caso de no acertar la pinta, puede depender de qué tan poco relacionada está la carta que juegan, respecto a la que se sacó aleatoriamente. Por ejemplo, una persona que juegue una carta de coronas, corazones, lunas u orbes, tratando de igualar la pinta de las espadas, podría quedar inconsciente (máximo daño, perdiendo la carta más alta en mano). Sin embargo, una que juegue una con la pinta de yelmos, sufriría un daño leve, mientras que el que juegue una carta de flechas o escudos, sufriría un daño moderado (perdiendo, por ejemplo, la carta más baja en mano), quedando en cierta forma limitado, aunque no inconsciente. Por ejemplo, pudiera ser incapaz de caminar sin ayuda.
River Pirate
Ability Scores Ability Codes Other Req.’s Advantages Disadvantages
Any. Any. Nature from Red Trump bonus for actions No trump bonus to Pr
aura card; for actions involving actions involving other
wealth between river travel. cultures; outsiders can’t
4 and 6. adopt the role during
play.
/***
|Name:|PrettyDatesPlugin|
|Description:|Provides a new date format ('pppp') that displays times such as '2 days ago'|
|Version:|1.0 ($Rev: 3646 $)|
|Date:|$Date: 2008-02-27 02:34:38 +1000 (Wed, 27 Feb 2008) $|
|Source:|http://mptw.tiddlyspot.com/#PrettyDatesPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License:|http://mptw.tiddlyspot.com/#TheBSDLicense|
!!Notes
* If you want to you can rename this plugin. :) Some suggestions: LastUpdatedPlugin, RelativeDatesPlugin, SmartDatesPlugin, SexyDatesPlugin.
* Inspired by http://ejohn.org/files/pretty.js
***/
//{{{
Date.prototype.prettyDate = function() {
var diff = (((new Date()).getTime() - this.getTime()) / 1000);
var day_diff = Math.floor(diff / 86400);
if (isNaN(day_diff)) return "";
else if (diff < 0) return "in the future";
else if (diff < 60) return "just now";
else if (diff < 120) return "1 minute ago";
else if (diff < 3600) return Math.floor(diff/60) + " minutes ago";
else if (diff < 7200) return "1 hour ago";
else if (diff < 86400) return Math.floor(diff/3600) + " hours ago";
else if (day_diff == 1) return "Yesterday";
else if (day_diff < 7) return day_diff + " days ago";
else if (day_diff < 14) return "a week ago";
else if (day_diff < 31) return Math.ceil(day_diff/7) + " weeks ago";
else if (day_diff < 62) return "a month ago";
else if (day_diff < 365) return "about " + Math.ceil(day_diff/31) + " months ago";
else if (day_diff < 730) return "a year ago";
else return Math.ceil(day_diff/365) + " years ago";
}
Date.prototype.formatString_orig_mptw = Date.prototype.formatString;
Date.prototype.formatString = function(template) {
return this.formatString_orig_mptw(template).replace(/pppp/,this.prettyDate());
}
// for MPTW. otherwise edit your ViewTemplate as required.
// config.mptwDateFormat = 'pppp (DD/MM/YY)';
config.mptwDateFormat = 'pppp';
//}}}
#Ten el coraje de hacer lo correcto.
#Conócete a tí mismo.
#Respeta la virtud.
#Está alerta.
#Todo el mundo merece justicia.
#Nunca te des por vencido.
El anteriormente bullicioso y próspero [[Puerto Balifor]] es ahora una ciudad fantasma, debido a los ataques de [[Malystryx]] "La Roja". Los residentes, liderizados por Renshar Morgenes, Harlowe Barstoll (un kender afligido) y Myra (una antígua Caballero del Lirio), han huído a las cuevas, fundando una colonia que ha crecido con el pasar de los días de la Quinta Era.
[img[Arte de Sandara3 en www.dlnexus.com|http://www.dlnexus.com/gfx/art/10511.jpg]]
El trono de Qualinesti es ocupado actualmente por Gilthas, hijo de [[Tanis|Thantalas]] Medio-Elfo y [[Laurana|Laurananthalasa]]. Es un títere desde el punto de vista político, controlado por los mismos Senadores y Militares que depusieron a su tío [[Porthios Khanan]] del trono de [[Qualinesti]]. La tierra es controlada por el Señor Dragon [[Beryl]], contra quien los Qualinesti tratan de luchar de forma infructuosa.
/***
|Name:|QuickOpenTagPlugin|
|Description:|Changes tag links to make it easier to open tags as tiddlers|
|Version:|3.0.1 ($Rev: 3861 $)|
|Date:|$Date: 2008-03-08 10:53:09 +1000 (Sat, 08 Mar 2008) $|
|Source:|http://mptw.tiddlyspot.com/#QuickOpenTagPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License:|http://mptw.tiddlyspot.com/#TheBSDLicense|
***/
//{{{
config.quickOpenTag = {
dropdownChar: (document.all ? "\u25bc" : "\u25be"), // the little one doesn't work in IE?
createTagButton: function(place,tag,excludeTiddler) {
// little hack so we can do this: <<tag PrettyTagName|RealTagName>>
var splitTag = tag.split("|");
var pretty = tag;
if (splitTag.length == 2) {
tag = splitTag[1];
pretty = splitTag[0];
}
var sp = createTiddlyElement(place,"span",null,"quickopentag");
createTiddlyText(createTiddlyLink(sp,tag,false),pretty);
var theTag = createTiddlyButton(sp,config.quickOpenTag.dropdownChar,
config.views.wikified.tag.tooltip.format([tag]),onClickTag);
theTag.setAttribute("tag",tag);
if (excludeTiddler)
theTag.setAttribute("tiddler",excludeTiddler);
return(theTag);
},
miniTagHandler: function(place,macroName,params,wikifier,paramString,tiddler) {
var tagged = store.getTaggedTiddlers(tiddler.title);
if (tagged.length > 0) {
var theTag = createTiddlyButton(place,config.quickOpenTag.dropdownChar,
config.views.wikified.tag.tooltip.format([tiddler.title]),onClickTag);
theTag.setAttribute("tag",tiddler.title);
theTag.className = "miniTag";
}
},
allTagsHandler: function(place,macroName,params) {
var tags = store.getTags(params[0]);
var filter = params[1]; // new feature
var ul = createTiddlyElement(place,"ul");
if(tags.length == 0)
createTiddlyElement(ul,"li",null,"listTitle",this.noTags);
for(var t=0; t<tags.length; t++) {
var title = tags[t][0];
if (!filter || (title.match(new RegExp('^'+filter)))) {
var info = getTiddlyLinkInfo(title);
var theListItem =createTiddlyElement(ul,"li");
var theLink = createTiddlyLink(theListItem,tags[t][0],true);
var theCount = " (" + tags[t][1] + ")";
theLink.appendChild(document.createTextNode(theCount));
var theDropDownBtn = createTiddlyButton(theListItem," " +
config.quickOpenTag.dropdownChar,this.tooltip.format([tags[t][0]]),onClickTag);
theDropDownBtn.setAttribute("tag",tags[t][0]);
}
}
},
// todo fix these up a bit
styles: [
"/*{{{*/",
"/* created by QuickOpenTagPlugin */",
".tagglyTagged .quickopentag, .tagged .quickopentag ",
" { margin-right:1.2em; border:1px solid #eee; padding:2px; padding-right:0px; padding-left:1px; }",
".quickopentag .tiddlyLink { padding:2px; padding-left:3px; }",
".quickopentag a.button { padding:1px; padding-left:2px; padding-right:2px;}",
"/* extra specificity to make it work right */",
"#displayArea .viewer .quickopentag a.button, ",
"#displayArea .viewer .quickopentag a.tiddyLink, ",
"#mainMenu .quickopentag a.tiddyLink, ",
"#mainMenu .quickopentag a.tiddyLink ",
" { border:0px solid black; }",
"#displayArea .viewer .quickopentag a.button, ",
"#mainMenu .quickopentag a.button ",
" { margin-left:0px; padding-left:2px; }",
"#displayArea .viewer .quickopentag a.tiddlyLink, ",
"#mainMenu .quickopentag a.tiddlyLink ",
" { margin-right:0px; padding-right:0px; padding-left:0px; margin-left:0px; }",
"a.miniTag {font-size:150%;} ",
"#mainMenu .quickopentag a.button ",
" /* looks better in right justified main menus */",
" { margin-left:0px; padding-left:2px; margin-right:0px; padding-right:0px; }",
"#topMenu .quickopentag { padding:0px; margin:0px; border:0px; }",
"#topMenu .quickopentag .tiddlyLink { padding-right:1px; margin-right:0px; }",
"#topMenu .quickopentag .button { padding-left:1px; margin-left:0px; border:0px; }",
"/*}}}*/",
""].join("\n"),
init: function() {
// we fully replace these builtins. can't hijack them easily
window.createTagButton = this.createTagButton;
config.macros.allTags.handler = this.allTagsHandler;
config.macros.miniTag = { handler: this.miniTagHandler };
config.shadowTiddlers["QuickOpenTagStyles"] = this.styles;
store.addNotification("QuickOpenTagStyles",refreshStyles);
}
}
config.quickOpenTag.init();
//}}}
SAGA tiene 7 categorías de rango, y se asume que en un turno de combate, puede cambiarse el rango de una categoría a otra contígua, mediante una maniobra de dificultad fácil (4). Las categorías son:
*''Supra-visual'': cuando un personaje no puede ver al otro, sin ayuda de magia o tecnología especializada. No pueden distinguirse detalles en este rango.
*''Visual'': los personajes pueden verse, pero no pueden interactuar. No pueden hablarse, aunque magia o tecnología especial pudiera remediar esto. Reconocer detalles se hace difícil, y apuntar es casi imposible sin magia o tecnología. Esta es la distancia en la que ocurren los encuentros en el mar y el aire, siempre y cuando las condiciones climáticas lo permitan.
*''Artillería'': un personaje puede golpear a otro con un arma realmente grande, como una catapulta, proyectil de cañon, etc. Aún no es posible hablar sin asistencia mágica o tecnológica, pero pueden distinguirse algunos detalles de apariencia. Esta es la distancia a la que ocurren los encuentros en grandes ríos, tejados de pueblos, sabanas.
*''Misil Lejano'': los personajes pueden verse y atacar con arco. Es la máxima distancia efectiva para las armas de misil de uso personal. La comunicación es posible mediante gritos. Esta es la distancia a la que ocurren los encuentros en bosques ligeros, ríos pequeños y caminos.
*''Misil Cercano'': Es la que los hobbits en El Señor de los Anillos llaman "distancia de tiro de piedra". Es difícil atacar con armas de artillería. La mayoría de los detalles visuales pueden ser percibidos, y la comunicación oral no requiere de gritos. Es la distancia en la que ocurren los encuentros en una calle de una ciudad, en un bosque, en un pantano o una ciudad).
*''~Cuerpo-a-Cuerpo'': Si un indivíduo puede golpear a otro en el rostro, están en Cuerpo-a-cuerpo. Es posible el uso de armas como espadas, garrotes, látigos, etc. La comunicación es posible mediante susurros. Apuntar armas de misil se hace casi imposible. Los detalles pueden perderse debido al movimiento o si el oponente es muy grande. Es la distancia en la que ocurren los encuentros al cruzar una esquina, o dentro de una cueva, casa o construcción, e incluso en una selva muy espesa.
*''Personal'': Si un indivíduo puede sentir el aliento del otro en el cuello, la distancia es personal. Ataques contínuos como agarres, llaves y sometimientos pueden mantener a un combatiente a ese rango. Es totalmente inútil cualquier tipo de ataque con armas de misil. Un susurro en rango personal puede no ser escuchado por nadie más.
Es la distancia respecto al Hechizero o Místico, a la que se produce el efecto mágico. Si el hechizo es un rayo, o se desplaza de forma lineal, es la distancia máxima a la que puede estar el oponente o objeto del conjuro.
Si el hechizo es de efecto expansivo en un área, el rango representa el punto central del hechizo, en líneas generales.
The Qualinesti Rebel
Since the Summer of Chaos, Qualinesti has been an occupied land. First, the Knights of Takhisis conquered it, then by the Green Peril. The office of the Speaker of the Sun has become but a mouthpiece for the land's oppressors.
Many elves simply hope that time will wash away their hardships. Others fight back. Qualinesti rebels take up weapons to drive the enemy from their land~r at least make the occupation as costly and difficult possible.
Porthios of House Solostaran, one-time Speaker of the Sun, now leads a band of Qualinesti rebels.
Role Playing:
In the Fifth Age, one might encounter many different shades of the Qualinesti freedom fighter: the disgusted mother who lost a child to the abuses of the Dark Knights; the idealistic youth who wants to drive out the invaders so his people can act as masters of their own fate again; and battle-hardened veterans who have seen more brutality than any elf ever should. The two unifying elements among all these character types are their hatred for Dark Knights and dragons, and their desire to return Qualinesti to elven control at virtually any cost.
Requirements:
As heroes with this role all belong to the race of Qualinesti elf or half-elf, they must meet the basic requirements for those races as described in Chapter One of the Book of the Fifth Age.
Advantages:
Qualinesti rebels form part of an underground network of warriors and rogues dedicated to freeing the elves from bondage. Much of this network actually exists beyond the boundaries of Qualinesti, where elves and half-elves secure weapons and supplies they then smuggle into the nation.
This hero knows a variety of secret signs and recognition codes that allow him to contact other members of the resistance inside or outside of Qua-linesti. He may contact any of his free-dom fighter acquaintances automatically; the hero knows a num-ber of resistance members equal to twice his total completed quests. (The Narrator and player should detail these contacts together).
Further, if a freedom fighter wants to contact resistance members in unfamiliar areas, he can seek out favorable locations-a seedy bar in a city's elven neighborhood, for example~and use the secret signs. The player should then turn over the top card of the Fate Deck. If the value of the card he draws equals or falls below the hero's current Quests score, he has successfully contacted another resistance member. (The Narrator can use the card's aura, portrait, or inscription to determine the other freedom fighter's disposition.)
Qualinesti rebels also receive the advantages listed for their race in Chapter One of the Book of the Fifth Age. Elf or half-elf heroes can acquire this role during play.
Disadvantages:
Freedom fighters lead brutal lives. They are engaged in a guerrilla war where neither side takes prisoners. And, on top of everything else, these elves often find themselves opposing their own neighbors or family mem-bers who chose to either support the Green Dragon or to remain neutral.
One cannot lead such a life and remain unaffected. After completing two quests in which the Qualinesti rebel has faced other elves in mortal combat, his nature undergoes a change. To reflect these harrowing experiences, the player must select a new nature for his hero from a card whose face value exceeds that of the card previously used. This rule simu-lates the progression many freedom fighters go through-they start out as idealistic souls but end up bitter and full of hate.
Qualinesti rebels also receive their normal racial disadvantages.
The Redeemer
By Eric Jwo
In ages past, people of faith dedicated themselves to the pantheon that ruled over Krynn. Every moment of their lives revolved around their deities. Through service to their respective gods and goddesses, clerics and priests across Krynn touched divinity, brushed immorality, and knew glory.
In one dark moment, this was all torn away. The Chaos god shattered the face of Krynn and tore away all traces of familiar magic. The gods fled from Krynn and left their worshippers bereft of divine guidance. People gave in to despair and hopelessness once they realized that they were alone. As Krynn entered its Fifth Age, people became more and more ensconched in their hopelessness. Terrible dragons waged war across the face of Ansalon and carved up the land for their own nefarious purposes. Many died in the face of the onslaught, and countless others were subjugated and conquered.
In this age of despair and fatality, the Redeemer emerges from the ravaging flames of war to provide salvation. Redeemers are extraordinary men and women who devote their lives to helping others. Traveling from area to area, Redeemers go where they are needed and do not remain anywhere too long. They are natural leaders and struggle to heal the spirits of others. In a land without gods, Redeemers struggle to spread their faith. Confident and pious, the Redeemer brings back hope to land shadowed by dragonwing.
Role-Playing
Redeemers are wholly devoted to their faith. Their entire life is based upon the belief that the gods are still watching. They spend their entire lives spreading the word and restoring hope throughout the land. Many would call their blind faith foolish, since many Redeemers were born after the departure of the gods and therefore never knew of them directly, but Redeemers defend their faith by stating that there is more to existence than what one can see.
Redeemers rarely judge others. They believe that it is not their place to judge others, but for the gods to do so. People don't need their judgement, they preach, but their compassion and understanding. However, that does not mean that a Redeemer does not recognize evil. Redeemers stay away from unsavory individuals and will take a stand against those that would harm others.
Redeemers, like Knights of Solamnia, help all those in need. They make no distinction between a wounded human or a wounded goblin, seeing in both cases, a person in need. This does not mean that a Redeemer will let his guard down, however, as a Redeemer will not risk his life needlessly.
However, a Redeemer places the life of others above his own. He will risk his own neck to save even what others deem to be the lowest forms of life. Redeemers base their life on helping others and spreading their faith.
However, a Redeemer's adherence to his faith does not make him as serious as many would believe. In fact, because of the hope and confidence that their faith brings them, Redeemers are amiable and charismetic. Seen as powerful and knowledgable individuals, Redeemers are often welcomed and accepted. They make friends easily and often find themselves thrust into positions of leadership. A palpable aura of strength surrounds all Redeemers.
Despite a Redeemer's ability to make allies, they often travel alone. A Redeemertravels from town to town in order to spread hope. He only stays in one place until he has completed his mission.
After that, he moves onward to anywhere else that needs him. However, Redeemers sometimes join adventuring parties if they believe that in doing so, they can help more people. However, since Redeemers believe that healing the spirit is more important than healing the body, they prefer to travel alone. If a Redeemer travels with companions, he will leave them at a moment's notice if they believe that they are needed elsewhere. A Redeemer values his mission above personal friendships.
Dwarves and minotaurs cannot fathom why a person would devote their entire lives to long departed gods. They believe that traveling around like a vagrant and preaching about missing deities is a waste of one's talents. Humans, kender, and centaurs, however, admire a Redeemer's outlook on life and appreciate their confidence and friendliness. Many elves do not believe that a member of any other race can seriously devote himself to a pious life, so Redeemers are met with suspicion if they are not elven.
Requirements
Since a Redeemer needs to tough in order to survive their strenuous life. Therefore, they need a minimum score of 5 in Endurance. Redeemers have great faith and determination. Therefore, they need a minimum score of 7 in Spirit. Redeemers also need to be confident and charismatic. Therefore, they need a minimum score of 7 in Presence.
Redeemers need to be experienced in both the power of the heart and in leading others. Therefore, they need a code of "A" in both Spirit and Presence. However, Redeemer's do not study the arcane or the weapons of war. Therefore, Redeemers have a maximum code of "B" in Reason, and a maximum code of "C" in Strength and Endurance.
Redeemers need to have their Demeanor and Nature scores drawn from cards with white auras. Since they do not care about money, Redeemers cannot have a Wealth score above 3 (that of a Commoner). Redeemers can be of any race that meets the requirements.
Advantages
Redeemers are so full of hope and energy that people are naturally drawn to them. Any Presence action when dealing with others is considered an automatic trump. Redeemers also get an automatic trump bonus to any action involving healing. This bonus includes attempts to give First Aid as well as attempts to cast spells from the mystic sphere of Healing.
Disadvantages
Redeemers are giving individuals, who do not hoard money. Therefore, any time a Redeemer receives any money or treasure, he must give it away. Whether this means donating to the nearest charity or giving a starving family a second chance, a Redeemer never spends the money that he receives needlessly.
Redeemers are also impelled to help any and all who need help. To avoid the temptation to aid a person, a Redeemer must make a Spirit action, with the difficulty depending on the severity of the situation. If a dog has its head caught in a hole, than it is an easy action, but if a person's life is in danger, than it is an impossible action.
/***
|Name:|RenameTagsPlugin|
|Description:|Allows you to easily rename or delete tags across multiple tiddlers|
|Version:|3.0 ($Rev: 5501 $)|
|Date:|$Date: 2008-06-10 23:11:55 +1000 (Tue, 10 Jun 2008) $|
|Source:|http://mptw.tiddlyspot.com/#RenameTagsPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License|http://mptw.tiddlyspot.com/#TheBSDLicense|
Rename a tag and you will be prompted to rename it in all its tagged tiddlers.
***/
//{{{
config.renameTags = {
prompts: {
rename: "Rename the tag '%0' to '%1' in %2 tidder%3?",
remove: "Remove the tag '%0' from %1 tidder%2?"
},
removeTag: function(tag,tiddlers) {
store.suspendNotifications();
for (var i=0;i<tiddlers.length;i++) {
store.setTiddlerTag(tiddlers[i].title,false,tag);
}
store.resumeNotifications();
store.notifyAll();
},
renameTag: function(oldTag,newTag,tiddlers) {
store.suspendNotifications();
for (var i=0;i<tiddlers.length;i++) {
store.setTiddlerTag(tiddlers[i].title,false,oldTag); // remove old
store.setTiddlerTag(tiddlers[i].title,true,newTag); // add new
}
store.resumeNotifications();
store.notifyAll();
},
storeMethods: {
saveTiddler_orig_renameTags: TiddlyWiki.prototype.saveTiddler,
saveTiddler: function(title,newTitle,newBody,modifier,modified,tags,fields,clearChangeCount,created) {
if (title != newTitle) {
var tagged = this.getTaggedTiddlers(title);
if (tagged.length > 0) {
// then we are renaming a tag
if (confirm(config.renameTags.prompts.rename.format([title,newTitle,tagged.length,tagged.length>1?"s":""])))
config.renameTags.renameTag(title,newTitle,tagged);
if (!this.tiddlerExists(title) && newBody == "")
// dont create unwanted tiddler
return null;
}
}
return this.saveTiddler_orig_renameTags(title,newTitle,newBody,modifier,modified,tags,fields,clearChangeCount,created);
},
removeTiddler_orig_renameTags: TiddlyWiki.prototype.removeTiddler,
removeTiddler: function(title) {
var tagged = this.getTaggedTiddlers(title);
if (tagged.length > 0)
if (confirm(config.renameTags.prompts.remove.format([title,tagged.length,tagged.length>1?"s":""])))
config.renameTags.removeTag(title,tagged);
return this.removeTiddler_orig_renameTags(title);
}
},
init: function() {
merge(TiddlyWiki.prototype,this.storeMethods);
}
}
config.renameTags.init();
//}}}
Because the SAGA system must be kept simple, the exact number of steel pieces that a hero has is not important. The SAGA system uses a wealth action, and like all other actions the Fate deck is used.
Any time that a hero need to buy something, a wealth action could be required. This simple chart can be used:
(Easy) up to 10 steel
(Average) up to 50 steel
(Challenging) up to 150 steel
(Daunting) up to 300 steel
(Desperate) up to 450 steel
(Impossible) up to 600 steel.
Trumps should be allowed if the player explains what his hero is doing [i.e. I try to impress the merchant (Pr. vs. Pr.) I try to trick the merchant (Re. vs. Pe.)]
Whenever the player receives a new amount of wealth, the narrator may allow for a wealth increase check. After the adventure where the hero acquires new wealth, he may draw the top card of the fate deck. If it is higher than his current wealth score, the score goes up by one.
(Note: Should a hero’s reputation increase in the same adventure he receives new wealth, he may attempt both a wealth increase and an ability score increase)
If a mishap should occur when the hero attempts a wealth action, the hero’s wealth score decreases by one. After all, one can only spend so much steel before he begins to go broke!
Despite several grim chapters in its history, the Knights ofsolamnia remains the preeminent order of chivalry in Ansalon. The Oath of these Knights, Est Sularus oth Mithas ("My honor is my life"), is widely imitated and serves as the standard for knightly conduct almost everywhere.
This role includes Knights and squires who have entered the Order, as well as heroes seeking admittance. The legendary Sturm Brightblade matched the Solamnic Knight role even before his formal induc-tion into the Order.
!Role-Playing:
A Knight of Solamnia follows the Measure, a set of rules that defines how to put the Oath into effect in one's daily life. The Knight must obey his superiors within the Order and remain steadfastly true to those who have earned his loyalty through station or past deeds. This courageous hero will make valiant sacrifices on behalf of the weak, the oppressed, the poor, the falsely imprisoned, and fellow Knights. He commits his life to justice and compassion.
The three Solamnic orders each emphasize a different aspect of the Measure, though all Knights are still expected to embrace this entire doctrine.
#The Order of the Crown Stresses obedience and loyalty.
#The Order of the Sword emphasizes courage, honor, and strength of spirit.
#The Order of the Rose epitomizes wisdom, justice and service to the cause of good.
A hero entering the Knighthood must begin as a squire in the Order of the Crown. Before he becomes a Knight of the Crown (or once a Crown Knight, before he can enter another order), he must demonstrate his commitment to the order's ideals (see pages 29 and 30 for more on these orders).
Knights of Solamnia can expect at least a grudging welcome wherever they go, except in areas controlled by a dragon or the Dark Knights. In regions under the Order's protection-Gunthar, Ergoth, and Solamnia-the common folk recognize Knights as their guardians and in some cases as representatives of civil authority.
!Requirements:
Ever ready to fight for a just cause, a Knight of Solamnia must have Strength and Endurance scores of at least 6. It takes a strong will to follow the Oath and the Measure, so he muSt have a Spirit score of at least 6 as well. The rigors of knightly life and total dedication to the Order's ideals tends to create an imposing figure. Therefore, a Knight must have a Presence score of at least 6.
A Knight of Solamnia must know the art of melee combat, which calls for a Strength code of "A." These warriors are known for their elaborate plate armor, translating into an Endurance code of "A."
As a Knight's emphasis on physical combat skills limits his ability to study magic at first, heroes with this role must begin play with Reason and Spirit codes of "C" at maximum.
Only civilized humans and half-elves should play the role of a Knight of Solamnia, as these are the only groups the Order admits. However, if a hero of another race feels inspired to live according to the Oath and the Measure due to his admiration for Solamnic principles, a Narrator can allow him to play the role.
Players may not select a card with a value higher than 4 for a Knight of Solamnia's demeanor in hero creation, nor use a card with a value higher than 5 to determine his nature. As the Knighthood offers its members at least minimal support, the hero's wealth score should be at least 3.
!Advantages:
Like a cavalier, a Solamnic Knight proves a bold and skillful leader in battle. Any card such a hero bids to close with the enemy is automatically trump.
The Knights of Solamnia also receive another, more unusual trump bonus. Solamnics resent both the Knights of Takhisis and the Legion of Steel for copying their organization and, in the Dark Knights' case, perverting their ideals. So, if a Solamnic enters combat against Knights of Takhisis or Legionnaires, any card he plays for a personal or melee attack becomes trump.
When riding a mount in a battle, any card a Knight plays to resolve a melee attack also becomes trump. However, this benefit is not cumulative with the one mentioned above.
Each order within the Knighthood has its own inherent advantages, too:
!!The Order of the Crown
Joining the Order of the Crown and advancing within (and beyond) it are detailed further in Chapter Two.
#On beginning play with this role, a hero becomes a squire in the Order of the Crown. When his reputation advances one category (or to the Adventurer rank, whichever is higher), the squire may become a Knight of the Crown.
#When the Knight's reputation moves up to the next category, he can peti-tion the Order for advancement. If successful, a Crown Knight can either advance to the Order of the Sword or immediately attempt to increase his Presence score, according to the rules at the end of Chapter One of the Book of the Fifth Age.
#A hero who remained a Knight of the Crown can repeat the petition again the next time his reputation advances one category.
!!The Order of the Sword
#As a Knight of the Sword, a hero enjoys an automatic improvement of one grade in his Spirit code, to a maximum of "B."
#The hero can petition the Order for advancement again the next time his reputation improves one category. Success means he can either immediately attempt to improve his Preseno' score or enter the Order of the Rose.
#Knights of the Sword can draw on Solamnic funds for their own (modest) needs and to further the causes of the Knighthood. When in contact with a local circle of the Knighthood, these heroes can access that circle's stores; in game terms, they may use onehalf their Presence scores instead of their wealth scores when attempting wealth actions.
!!The Order of the Rose
#As a Knight of the Rose, a hero auto-matically increases his Spirit code by one grade, to a maximum of "A."
#When these high ranking Knights successfully petition the Order for advancement after an increase in reputation, they can immediately attempt to improve their Presence score.
#When drawing on the Knighthood's treasury (as described above for Knights of the Sword), a Rose Knight can use his full Presence score instead of his wealth score when attempting a wealth action.
!Disadvantages:
A Knight of Solamnia's rigid code of honor imparts several drawbacks Onto this role to counter its benefits. First, as an honorable combatant, a Knight never enjoys a trump bonus to achieve surprise before combat. As a Knight's honor is his life, his Presence score immediately falls I point if he should so shame himself as to fail a petition for advancement. Further, if the Narrator ever thinks the Knight has violated the Measure (see page 35), the hero must attempt a daunting Presence action, immediately losing 1 point of Presence if he fails. Should the Knight commit a serious breach of conduct, a knightly council can call him to answer for his actions.
Knights of Solamnia are loath to retreat from or refuse combat with Evil foes. No Knight will retreat from a battle once it has begun or refrain from attack-ing the Order's foes (see page 31), unless he considers the fight foolish or useless. To tear himself away from combat, the Knight must succeed in the action below:
!!Abandon/Refuse a Fight
''Difficulty'' Varies
''Action ability'' Reason
''Opposition ability'' Presence (only intelligent foes)
''Comments'': The difficulty of this action depends on the hero's order:
#''Crown Knight'': Average (8)
#''Sword Knight'': Challenging (12)
#''Rose Knight'': Daunting (16)
In addition, this action always becomes easy when an enemy of equal or greater Strength (or Physique) outnumbers the Knight and his group at least three to one.
If a trusted ally urges the hero to refuse or abandon a fight, the ally adds his Presence score to the Knight's Reason score for this action.
A higher ranking Knight (one with a greater reputation or official office, as
described on page 28) can order the hero away from a fight, but the superior must succeed in this action himself before he can issue the order.
As a Knight finds no dishonor in liv mg to fight another day, he may add his foe's Strength (or Physique) score to his Reason score for this action.
Mishap: The Knight's foe gets a free counterattack outside the normal comb sequence.
Like cavaliers, Knights of Solamnia owe forty to sixty days of direct service to the Order each year. (The rest of the year, a Knight can either continue to serve the Order or can pursue personal adventure The Knighthood encourages such quests as a means of strengthening character.) The Narrator can devise a quest for the Knight and his companions during this period, or the hero can simply leave the game for a time. In the latter case, the player must use a different hero. However Knights take part in many adventures as part of their period of service.
Knights are expected to donate most of their wealth to the Knighthood, including extra income from their ancestral estates. Each time a hero's reputation advances to the next level, his wealth score falls 1 point, to a minimum of 2. Experienced Knights can have lower wealth scores than the poorest Novices. However, they can use their Presence scores to access the Order's treasury, as described under 'Advantages"
To become a true Knight of Solamnia, a hero must begin preparing himself during his youth. Therefore, heroes may not acquire this role during play, though most can join the Order as auxiliaries (see page 33).
[img[Arte por Sandara3 en www.dlnexus.com|http://www.dlnexus.com/gfx/art/10755.jpg]]
[>img[Arte de Hugh Vogt en www.dlnexus.com|http://www.dlnexus.com/gfx/art/20476.jpg]]The Knights of Solamnia are Ansalon´s oldest and most respected Order of chivalry Although the Order itself is composed exclusively of warriors, the Knights have learned the value of having members from more diverse backgrounds (the events of the Summer of Chaos particularly proved the value of sorcerers in martial activities). While the Knights did not actually open their ranks to all types of heroes, they did create an auxiliary which anyone who follows the Solamnic ideal can join. Solamnic auxiliary sorcerers gain many of the privileges of the newest members of the Order of the Crown: respect, support (both moral and financial), and the satisfaction that comes from representing the forces of goodness and mercy.
Palin Majere, as a young man, traveled with his Knight brothers as an unofficial auxiliary sorcerer.
* Roleplaying
Members of the Solamnic auxiliary are expected to follow the same principles as the Knights themselves. They must all swear the Solaminc Oath, Est Sularus oth Mithas ("My honor is my life") and folow the Measure, a set of rules which tell how to put the Oath to use in daily life. An auxiliary sorcerer must obey the orders of his superiors in the auxiliary as well as those of all Knights of Solamnia (Knights automatically outrank auxiliary members). He must remain faithful and true to all those who have earned his loyalty, and is required to protect and make sacrifices in the name of the poor, weak, oppressed, and falsely imprisoned. The Solamnic´s main goal in the Fifth Age is to protect the people of Ansalon from the Great Dragons and the Knights of Takhisis, but their honor demands that, even in this endeavor, they not overlook smaller transgressions against the people.
The Solaminc ideal is not an easy one to follow. Heroes who choose this role will have to be shining examples of honor, virtue, and chivalry. They must not actually be Solamnic Knights, but they do wear the kingfisher crest and the Order is particular about exactly how and by whom it is represented. The Knights expect nothing short of perfection from themselves, and they are equally demanding of their auxiliary members.
* Requirements
While the Knights themselves admit only civilized human and half-elf warriors in their ranks, the auxiliary is open to anyone who meets the rigid chivalric standards for entrance. Sorcerer heroes are more likely to encounter aloofness among the Knights because of their profession than from any kind of racism, for the Knights are not entirely comfortable with sorcery yet.
Auxiliary members need not meet all the physical requirements demanded of Knights, but there is a level of martial discipline the Order demands of all its representatives. Since they are not likely to engage in physical battle, sorcerer applicants have no combat requirements; however, they will be expected to accompany Knights on maneuvers and keep up with them, should hostilities break out. Therefore, auxiliary sorcerers must have Endurance scores of no less than 6, the same as a member of the Order.
More important than physical ability or martial prowess, however, is an auxiliary member´s character and personality. People all across Ansalon will be able to recognize instantly these heroes as representatives of the Solamnic Order, even if they see them only in passing. It is therefore of the utmost importance that these heroes embody the same beliefs and principles the Knights do. They are thus held to the same temperamental restrictions as are candidates for the Order. During hero creation, an auxiliary sorcerer may not select a demeanor from a card with a score higher than 4, nor may he have a nature taken from a card with a score higher than 5.
* Advantages
Members of the Solamnic auxiliary gain many benefits from their association with the Order. One whose value is often overlooked is the boost that association with the Solamnics gives to their reputation. The kingfisher crest will open many doors that otherwise would be barred to the heroes. When dealing with Knights, or any character or group subordinate to the Order, heroes who belong to the auxiliary are treated as though their reputation was one quest higher than it is. This may increase the maximum size of his Hand of Fate. If this is the case, however, the player should not draw an extra card. Every time the hero attempts an action with his increased reputation, he should draw a bouns card and look at it; he now has the choice of playing the bouns card or one from his normal hand. If he chooses to use the bonus card, he does not draw a replacement. If he chooses to use a card from his hand, he discards the bonus card as well and then draws from the Fate Deck to replenish his hand. The bonus card must either be used or discarded; it may not be added to the hero´s permanent hand.
Of course, the Order itself, with its resources, is a great advantage to those working in its name. While auxiliary members do not have the automatic right to draw upon the Knights´ treasury, they can count on substantial support (in terms of both money and manpower) for any officially sanctioned endeavor in which they are involved. Heroes on a quest for the Solamnics will always be properly equipped.
* Disadvantages
There are, naturally also some responsabilities which come with membershio in the Solamnic auxiliary. The MEasure itself can seem like a terrible burden to heroes not wholeheartedly committed to Solamnic ideals. The life of a Knight is never truly his own. He is always expected to put others (particularly the poor and downthrodden) before himself. Things are not quite so rigorous for auxiliary members, but they are expected to devote at least forty days a year to direct service to the Order.
A drawback of joining the auxiliary which few applicants consider is the might of the Knight´s adversaries. Being the most powerful force for chivalry and honor on Ansalon, the Solamnic Knights face the collected animosity of nearly every Evil creature on the continent, and as sanctioned representatives of the Order, so do all auxiliary members. This shoud not shock heroes who choose this role. After all, part of their job is to seek out and battle Evil wherever it hides. However, they may not have realized that the Evil forces of the world will be hunting them at the same time. With Great Dragons, the Knights of Takhisis, and all manner of magical monsters in their ranks, the forces of darkness on Krynn are more cunning and dangerous than ever before.
It is possible, though a challenge, for sorcerer heroes to join the Solamnic auxiliary during play. This requires on eextra step after meeting all the requirements listed above. (At the Narrator´s discretion, this step may be required as well as beginning heroes planning to play this role.) In order to be accepted into the auxiliary, the hero must first stand before a knightly council and face a Knight´s Trial to prove his worthiness and devotion to the principles he will be asked to embody. If the hero succeeds at this action, the council has found him worthy and he is immediately recognized as a member of the Solamnic auxiliary.
- Knight´s Tial
Difficulty: Average (8)
Action Ability: Presence
Opposition Ability: Presence
Comments:
To be accepted into the Solamnic auxiliary, an applicant must succeed at the Knight´s Trial action. This is opposed by the member of the presiding knightly council with the highest reputation. The trial consists of the applicant formally presenting himself for consideration (stating his name, lineage, and any accomp´lishments of note), answering an arduous series of questions designed to root out attitudes and beliefs which run counter to the Solamnic Measure, and finally defending himself against a direct attack against his character (taken from facts gleaned earlier in the interview). The final segment is notorious for leaving even the most stout-hearted applicants demoralized.
If the hero fails at the Knight´s Trial, he may attempt it again as many time as he wishes. However, between each attempt, he must complete a quest assigned to him by the knightly council.
Should the interview reveal that the hero has, in the past, behaved in ways inappropiate for a Solamnic representative, the council may require him to perform a task or complete a quest to prove his honor.
Mishap:
The hero has made a terrible faux pas, an embarrassing fact about his past has come up, or a council member believes he is not remotely qualified. For the purpose of any interactions with representatives of the Order (Knights or auxiliary members), the hero permanently loses 1 point of Presence.
[img[Arte de Canlocu en www.dlnexus.com|http://www.dlnexus.com/gfx/art/22915.jpg]]
[img[Arte de Nick Barfuss de www.dlnexus.com|http://www.dlnexus.com/gfx/art/19661.jpg]]
[>img[Arte de Sandara3 en www.dlnexus.com|http://www.dlnexus.com/gfx/art/10793.jpg]]
El rol de un Héroe indica cómo sus antecedentes afectan su forma de vida actual, como por ejemplo:
*Su infancia
*Sus creencias
*Sus intereses
Esto permite a los jugadores dar más profundidad al representar al héroe.
Adicionalmente, en términos de reglas de juego, gana nuevas habilidades y limitaciones cambiando así lo que es factible e infactible para el personaje.
Un Héroe no puede cambiar fácilmente de rol.
El rol exacto que un jugador escoge para su héroe, es una decisión suya, aunque el Narrador podría declarar que ciertos roles son inapropiados para su campaña o aventura.
Por último, es importante aclarar que los roles no son una lista finita de opciones pre-fabricadas. Sin embargo, en las diferentes publicaciones de Dragonlance SAGA han sido definidas unas como ejemplo, que satisfacen la mayoría de los tipos de personaje que pueden querer jugarse. Pueden servir de ejemplo para que el Narrador cree, junto a sus jugadores nuevos roles.
!¿Qué es SAGApedia?
SAGApedia es un archivo que permite acceder de forma rápida y breve a los diferentes tipos de información que pueden ayudar al jugador de Dragonlance con el Sistema SAGA.
Incorpora información de:
*El Setting Oficial de DragonLance (especialmente la [[Quinta Era]] o Era de los Mortales).
*Reglas opcionales creadas por los aficionados a DragonLance y al Sistema SAGA.
Desde el punto de vista técnico, SAGApedia es un archivo construído con tecnología [[TiddlyWiki]].
/***
|Name:|SaveCloseTiddlerPlugin|
|Description:|Provides two extra toolbar commands, saveCloseTiddler and cancelCloseTiddler|
|Version:|3.0 ($Rev: 5502 $)|
|Date:|$Date: 2008-06-10 23:31:39 +1000 (Tue, 10 Jun 2008) $|
|Source:|http://mptw.tiddlyspot.com/#SaveCloseTiddlerPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License:|http://mptw.tiddlyspot.com/#TheBSDLicense|
To use these you must add them to the tool bar in your EditTemplate
***/
//{{{
merge(config.commands,{
saveCloseTiddler: {
text: 'done/close',
tooltip: 'Save changes to this tiddler and close it',
handler: function(ev,src,title) {
var closeTitle = title;
var newTitle = story.saveTiddler(title,ev.shiftKey);
if (newTitle)
closeTitle = newTitle;
return config.commands.closeTiddler.handler(ev,src,closeTitle);
}
},
cancelCloseTiddler: {
text: 'cancel/close',
tooltip: 'Undo changes to this tiddler and close it',
handler: function(ev,src,title) {
// the same as closeTiddler now actually
return config.commands.closeTiddler.handler(ev,src,title);
}
}
});
//}}}
Un combate está compuesto por una serie de ataques y contraataques, hasta que alguno de los combatientes es neutralizado, o huye:
!0. Determinar rango del encuentro
Es importante que el narrador decida esto antes de iniciar el combate.
!1. Sorpresa
Al comienzo del combate, el Narrador decide, basándose en la situación, si uno de los lados sorprende al otro. Si uno de ellos es sorprendido, el contrario disfruta de un ataque gratis, sin que éste sea respondido (en general todo ataque viene acompañado de un contraataque, por lo que esto es una excepción).
!2. Declaración de Acciones
Cada jugador debe informar lo que desea hacer en su turno, principalmente es importante saber si la acción será física o mental, y cuál será el arma o implemento a utilizar.
!3. Iniciativa
Se determina quién actúa primero. Para ello se hacen chequeos de iniciativa, y el que tenga el mayor resultado, da el primer golpe. Esto puede ser importante, porque el primer golpe podría ser mortal o incapacitante. En las reglas oficiales, el Héroe siempre ataca primero, pero como regla opcional se puede determinar el valor de iniciativa así:
{{{Valor de Iniciativa = Agilidad + Carta - (daño del arma) - (defensa de escudo) - (defensa de armadura) + (código de habilidad de ataque)}}}
Como puede verse, tienen más oportunidades los personajes con alta agilidad, armas, escudo y armadura ligeros, y de mayor entrenamiento en la habilidad de ataque (típicamente Fuerza o Destreza). Las cartas de Escudos son Cartas de Triunfo para el chequeo de iniciativa.
El valor por código es: {{{A = 4}}}, {{{B = 3}}}, {{{C = 2}}}, {{{D = 1}}}, {{{X = 0}}}
En mi grupo de juego, cuando un jugador declara que hará un ataque mágico, usamos la siguiente fórmula:
{{{Valor de Iniciativa = Perception + Carta - (dificultad base del hechizo) - (defensa de escudo) - (defensa de armadura) + (código de habilidad de ataque)}}}
Esto hace que se vean favorecidos quienes hagan hechizos de poca complejidad, con poca armadura, sin escudo y con alto nivel de entrenamiento en Hechicería o Misticismo, según sea el caso. Las cartas de Orbes son Carta de Triunfo en esta ocasión.
!4. Ataques y Defensas
Cada héroe realiza su ataque o defensa (si ganó iniciativa el oponente).
!!Ataques
En combates de misil, típicamente la acción es de dificultad promedio (8) con Destreza, resistido por Agilidad. En Combate Cuerpo-a-Cuerpo la dificultad es promedio, típicamente (8) y la agilidad es Fuerza, opuesto por Resistencia.
Si la acción de ataque es exitosa, las reglas oficiales dicen que el daño constante, e igual a la suma de la habilidad más el daño del arma utilizada. Sin embargo, existe esta regla opcional:
{{{Daño = Habilidad + Daño del Arma Usada - Defensa de Armadura del Oponente - Defensa de Escudo del Oponente}}}. Si el resultado es positivo, hay daño. Si el resultado es negativo, la defensa fue efectiva (ya sea por evasión o por haber deflectado el golpe con armadura o escudo).
!!Defensas
El Héroe se defiende del ataque del enemigo, haciendo un chequeo. El Narrador no lanza el ataque del enemigo, a menos que se trate de un personaje sumamente importante en la historia. Usualmente la defensa contra un ataque de misil es de dificultad promedio (8), la habilidad es Agilidad, y es resistida por la Destreza del enemigo. Si la defensa es contra un ataque Cuerpo-a-Cuerpo, la situación es la misma, típicamente, pero la Habilidad es Resistencia, opuesta por la Fuerza del oponente. Si el ataque es con Hechicería o Misticismo, se resiste con Percepción o Presencia, respectivamente, opuestos por Razonamiento o Espíritu del oponente.
El daño se calcula de forma análoga, pero los puntos restantes deben ser "pagados" mediante cartas de la Mano, que no son repuestas con cartas nuevas del Mazo del Destino.
!5. Determinar las heridas.
Un personaje puede, según las reglas oficiales, soportar un número de heridas igual a su valor de Resistencia, antes de caer inconsciente.
Por su lado, sin un héroe se queda sin cartas luego de asumir el daño recibido, el héroe queda inconsciente. Vale la pena acotar que para "asumir" daño tanto cartas Corazón como cartas de Yelmos son Cartas de Triunfo.
[[Acciones Avanzadas en Combate]]
[[Luego de un Combate]]
/***
|Name:|SelectThemePlugin|
|Description:|Lets you easily switch theme and palette|
|Version:|1.0.1 ($Rev: 3646 $)|
|Date:|$Date: 2008-02-27 02:34:38 +1000 (Wed, 27 Feb 2008) $|
|Source:|http://mptw.tiddlyspot.com/#SelectThemePlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License:|http://mptw.tiddlyspot.com/#TheBSDLicense|
!Notes
* Borrows largely from ThemeSwitcherPlugin by Martin Budden http://www.martinswiki.com/#ThemeSwitcherPlugin
* Theme is cookie based. But set a default by setting config.options.txtTheme in MptwConfigPlugin (for example)
* Palette is not cookie based. It actually overwrites your ColorPalette tiddler when you select a palette, so beware.
!Usage
* {{{<<selectTheme>>}}} makes a dropdown selector
* {{{<<selectPalette>>}}} makes a dropdown selector
* {{{<<applyTheme>>}}} applies the current tiddler as a theme
* {{{<<applyPalette>>}}} applies the current tiddler as a palette
* {{{<<applyTheme TiddlerName>>}}} applies TiddlerName as a theme
* {{{<<applyPalette TiddlerName>>}}} applies TiddlerName as a palette
***/
//{{{
config.macros.selectTheme = {
label: {
selectTheme:"select theme",
selectPalette:"select palette"
},
prompt: {
selectTheme:"Select the current theme",
selectPalette:"Select the current palette"
},
tags: {
selectTheme:'systemTheme',
selectPalette:'systemPalette'
}
};
config.macros.selectTheme.handler = function(place,macroName)
{
var btn = createTiddlyButton(place,this.label[macroName],this.prompt[macroName],this.onClick);
// want to handle palettes and themes with same code. use mode attribute to distinguish
btn.setAttribute('mode',macroName);
};
config.macros.selectTheme.onClick = function(ev)
{
var e = ev ? ev : window.event;
var popup = Popup.create(this);
var mode = this.getAttribute('mode');
var tiddlers = store.getTaggedTiddlers(config.macros.selectTheme.tags[mode]);
// for default
if (mode == "selectPalette") {
var btn = createTiddlyButton(createTiddlyElement(popup,'li'),"(default)","default color palette",config.macros.selectTheme.onClickTheme);
btn.setAttribute('theme',"(default)");
btn.setAttribute('mode',mode);
}
for(var i=0; i<tiddlers.length; i++) {
var t = tiddlers[i].title;
var name = store.getTiddlerSlice(t,'Name');
var desc = store.getTiddlerSlice(t,'Description');
var btn = createTiddlyButton(createTiddlyElement(popup,'li'), name?name:t, desc?desc:config.macros.selectTheme.label['mode'], config.macros.selectTheme.onClickTheme);
btn.setAttribute('theme',t);
btn.setAttribute('mode',mode);
}
Popup.show();
return stopEvent(e);
};
config.macros.selectTheme.onClickTheme = function(ev)
{
var mode = this.getAttribute('mode');
var theme = this.getAttribute('theme');
if (mode == 'selectTheme')
story.switchTheme(theme);
else // selectPalette
config.macros.selectTheme.updatePalette(theme);
return false;
};
config.macros.selectTheme.updatePalette = function(title)
{
if (title != "") {
store.deleteTiddler("ColorPalette");
if (title != "(default)")
store.saveTiddler("ColorPalette","ColorPalette",store.getTiddlerText(title),
config.options.txtUserName,undefined,"");
refreshAll();
if(config.options.chkAutoSave)
saveChanges(true);
}
};
config.macros.applyTheme = {
label: "apply",
prompt: "apply this theme or palette" // i'm lazy
};
config.macros.applyTheme.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
var useTiddler = params[0] ? params[0] : tiddler.title;
var btn = createTiddlyButton(place,this.label,this.prompt,config.macros.selectTheme.onClickTheme);
btn.setAttribute('theme',useTiddler);
btn.setAttribute('mode',macroName=="applyTheme"?"selectTheme":"selectPalette"); // a bit untidy here
}
config.macros.selectPalette = config.macros.selectTheme;
config.macros.applyPalette = config.macros.applyTheme;
config.macros.refreshAll = { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
createTiddlyButton(place,"refresh","refresh layout and styles",function() { refreshAll(); });
}};
//}}}
Cuando se instala un campamento, o se detiene en su viaje, usualmente se nombra a un sentinela, o guardia, para asegurarse de no ser sorprendidos por algún enemigo. Suele ser quién tenga mayor Percepción.
The Death Lord is a mystic who, after years of training, has been able to control death, at least to a limited extent. There are two types of Death Lords, the first seeks to put the walking dead (whom he calls "the lost") to rest. He sees them as poor souls longing for the comfort of the grave. This Type of Death Lord asks the question "Why should they be forced to roam the world in the end?" They are not evil, he says, simply lost in death. He seeks to help them.
The second type of Death Lord seeks these wandering dead so he can control and rule over them. He creates them in vile magic and binds them to his service.
!Role Playing:
The first type of Death Lord should be played as a kind, but somewhat morbid person. While he seeks to only do well in the world, his profession is somewhat dark. He also, due to his dealing with the dead, understands little about the workings of the living mind.
The second type, is truly evil, and seeks nothing but to control. Playing this type of Hero should not be done without a good reason.
!Requirements:
A hero of the first type of Death Lord must use a card with a white block for both his Nature and Demeanor. A Hero of the second must use one with a black block.
Because in his occupation the Death Lord often deals with vile diseases, an Endurance of 8 is the minimum. Because he prefers to use his magic to weapons, all physical abilities cannot reach higher than an ability code of "C" The Death Lord must employ the strongest of mystic magic, a Minimum of 7"A" must be met and kept to take this role. A high Presence is also recommended.
!Advantages:
Due to his dealing with the dead, all actions against undead, are considered trump, as are all spell from the Necromancy and Spiritualism spheres.
!Disadvantages:
For the same reason he receives the advantages above, the Death Lord has little dealing with the living, and as such gains no trump bonuses when acting against them, except when employing the spheres of Necromancy and Spiritualism. Heroes of this role may never learn the spheres of Animism, Alteration or Healing.
The Animal Master Role
Role-Playing
These Heroes have a special affinity with animals or creatures from the nature. Heroes with a white Nature protects and takes care of them and black Nature uses them to their advantages. They are trainers, guardians and keepers of these animals. Usually, Animal Masters are from the lowest classes.
Requirements
To be an Animal Master, you must have a Social Status between Slave and Tradesman. The minimum Endurance score must be of 6 and Perception of 7. It is open to every races.
Advantages
The Animal Master has a suitable animal companion. The Master must consider the climate and the terrain of the master's homeland and the Heroe's Nature and Race. The special companion has a close bond with his master. The Animal Master can give some simple verbal and visual command. The animal can be choosen by the Narator or selected randomly. Draw 2 Cards and consult the following table:
Score Companion
2 Badger
3 Dog
4 Wolf
5 Snake
6 Brush Rat
7 Owl
8 Ferret
9 Raven
10 Squirrel
11 Raccoon
12 Opossum
13 Fox
14 Skunk
15 Cat
16 Falcon
17 Monkey
18 Hawk
Also, the Animal Master gains a +4 bonus to calm a panicked tame animal Action or related actions.
Disadvantages
The Hero must protect his companion. He must not send him in a dangerous place and if it happens and he looses his companion by his fault, the Hero looses 1 Endurance Point and loses his special affinity with the race of his dead companion and he can't gain another one from the same type. If the animal dies from natural causes or others, the Hero has no penalties.
|!Valor de Habilidades|!Códigos de Habilidades|!Otros Req.|!Ventajas|!Desventajas|
|Los de todas las habilidades físicas deben ser 4 min (tribus agresivas nada más); Espíritu 5 min|Espíritu B min|Must have a barbarian upbringing; spiritualism sphere required.|Trump bonus for spellcasting in trump sphere (animism or spiritualism); trump bonus for outdoor actions in home terrain. |No trunmp bonus for PR actions to deal with "civilized" folk; must use [[Tribal weapons|Armas Tribales]]; cannot adopt role during play. |
Kagonesti Shaman
Ability Scores Ability Codes
AG 6 min AG D max
DX 6 min DX B min
RE 4 min/7 max EN D max
PE 6 min ST B max
SP 5 min RE B
PR 6 min SP B min
Other Requirements: Kagonesti elves only; animism and one elemental school required.
Advantages
Trump bonus in combat w/straight or recurved bow, when using PE, moving silently, or hiding in the forest, and for animism; enchant arrows; +3 bonus to PR actions involving animals.
Disadvantages
NO trump bonus for PR actions w/other races (except to resist mystic magic); -6 PR action penalty for dealing with Silvanesti and -3 penalty for Qualinesti; forbidden spheres and schools; cannot adopt role during play.
[>img[Arte de Icegal en www.dlnexus.com|http://www.dlnexus.com/gfx/art/10855.jpg]]
Silvanesti- Silvanesti now sits behind a magical shield, known to some as the Sylvan veil. They are ruled by General Konnal of House Protector, who in the absence of a speaker has named himself Military Governor. General Konnal ordered the raising of the shield with the advice of [[Rillion Dawnbringer]], a mysterious elf from the House Woodshaper, who has been lost in the forests of Silvanesti since Loracs nightmare to return after the chaos war. No living thing can pass from either side through the shield.
The Silvanesti elves have learned that their shield comes with a heavy price. The shield has drained the life energy of the forest, its plant life and the animals and creatures that inhabit it. The only people with the power to change the shield, the elders of house Woodshaper, have also started to die, and to make things worse the evil dragon Cyan Bloodbane is trapped behind the shield, to once again terrorise the Silvanesti elves.The people of Silvanesti are sick and weak while the elders and the very young are dying, while the shield drains all the life of their forests.
It has recently come to light that the mysterious elf Rillion Dawnbringer, who influenced the raising of the deadly shield and now sits in a position of high authority, is actually an agent of [[Cyan Bloodbane]], and it was Cyan in the shape of an elf that brought Dawnbringer to the attention of Konnal.
Algunas veces los personajes necesitan de un nivel más avanzado de detalle en la definición de lo que pueden hacer y lo que no pueden hacer. Las Pericias engloban:
*Los talentos, o cosas que el personaje tiene natural e intuitiva disposición para realizar ciertas cosas.
*Las técnicas y experticias, o cosas que el personaje ha aprendido y practicado para poder tener el dominio que tiene.
Hay varios sistemas:
#''Pericia General'': Todos los héroes se asumen como potencialmente capaces de utilizar cualquier skill relacionada con sus habilidades, teniendo como guía los códigos de las mismas.
#''Pericias Profesionales'': Los héroes tienen algunas pericias especializadas aunque aún difusas, como:
*Granjero
*Herrero
*Escriba
Estas pueden considerarse como profesiones o actividades que el héroe podría haber realizado antes de aventurear, o también como hobbies. Un personaje podrá tener tantas pericias como el [[Número de Retos]] que aparezca escrito en su hoja de personaje. El tener un skill de estos, usualmente da un Bono de Carta de Triunfo a cualquier acción relacionada con esa profesión u oficio. Esto puede ser una buena opción en general para juegos de fantasía medieval. Esto debe considerarse de forma adicional a las pericias indicadas por el código de las habilidades.
#''Pericias Múltiples'': Es la más elaborada de las formas de considerar las pericias. Los héroes tienen múltiples pericias en áreas específicas. Están subdivididas en 4 grandes categorías asociadas a un tipo de habilidad ([[Físicas|Pericias Físicas]], de [[Coordinación|Pericias de Coordinación]], [[Inelectuales|Pericias Intelectuales]] y de [[Esencia|Pericias de Esencia]]). Los códigos de habilidades determinan cuántos skills en cada tipo de habilidad posee el héroe:
*A=4
*B=3
*C=2
*D=1
*X=0
Para las habilidades de cada tipo se hace un promedio entre los valores de las dos habilidades que la componen. Ejemplo: si se tiene Fuerza A y Resistencia D, el #Pericias = (4+1)/2 = 2,5 ~ 2 pericias
Estas podrían ser: Nadar y Montañismo. Las pericias usados de esta forma le dan al héroe un +4 a la acción.
__Opcional__: Puede haber grados para las pericias, en el sentido de que teniendo esos 2 "puntos" en el ejemplo, podrían asignarse a la misma pericia, para tenerla en un nivel más avanzado. Los niveles son:
*//Pericia Normal//: El héroe tiene +4 para su acción / opcionalmente, puede obtener Carta de Triunfo jugando una carta de la pinta asociada a la acción, o de la habilidad asociada (ejemplo: Fuerza y Resistencia son habilidades asociadas, y por ende tanto Espadas como Yelmos darían carta de Triunfo, si la pericia es del área física).
*//Maestría//: El héroe tiene +8 para su acción / opcionalmente, puede obtener Carta de Triunfo jugando cualquier carta con pinta del mismo tipo (Físico o Mental) (ejemplo: si la pericia es física, las cartas de Flecha, Escudo, Yelmo y Espada permiten el uso de Carta del Trinfo).
*//Excelencia//: El héroe tiene +12 para su acción / opcionalmente, cualquier carta que no sea Dragón permite el uso de Carta de Triunfo.
Las Ventajas y Desventajas añaden otro nivel de complejidad y profundidad al sistema SAGA.
Usualmente (según las reglas oficiales) las ventajas y desventajas de un personaje, las tiene sólo en función de su raza (ejemplo: los elfos son arqueros y espadachines legendarios), y en función del rol (ejemplo: los Caballeros de Takhisis tienen especial debilidad ante la magia mística).
Sin embargo, hay Ventajas y Desventajas que pueden ser características individuales, como por ejemplo ser ambidiestro, o tener fobia a las alturas. Estas deben ser adquiridas durante la creación del personaje, aunque bajo circunstancias especiales, algún evento en el juego puede provocar la aparición de una ventaja o desventaja.
Una práctica usual, es que durante la creación del personaje, no se permita tener más ventajas y desventajas que el [[Número de Retos]] del [[Héroe]]. Una vez terminada la construcción estándard del personaje, se puede proceder a asignar las ventajas y desventajas. En general pueden añadirse en relación uno a uno, siempre y cuando tengan impactos similares. Si se desea añadir sólo una ventaja o una desventaja, a juicio del narrador debe haber ajustes en la hoja de personaje. Posiblemente disminuír o aumentar alguna habilidad (en valor o código), estatus social, tamaño de mano, etc.
Guía rápida del Sistema SAGA para DragonLance
[img[Image from Wikipedia|http://upload.wikimedia.org/wikipedia/en/5/59/Dragonlance-Logo-Orig.png]]SAGApedia
Solace se encuentra bajo constante amenaca, ya que está justo al norte de las tierras de [[Beryl]] "La Verde" y la cercana [[Pax Tharkas]] ha sido prácticamente destruída. Solace ahora se ha vuelto, prácticamente, una ciudad "universitaria", puesto que en sus afueras [[Palin Majere]] fundó la [[Academia de Hechicería]], y la [[Legión de Steel]] decidió instaurar su cuartel central. Por si fuera poco, en Solace yace la [[Tumba de los Últimos Héroes]], en donde descansan [[Tanis|Tanthalas]] Medio-Elfo, [[Steel Brightblade]], los bolsos de [[Tasslehoff Burrfoot]] y los [[Caballeros de Solamnia]] y de [[Takhisis|Caballeros de Takhisis]] que dieron sus vidas defendiendo a [[Krynn]] del dios [[Caos]].
The Storm Mage is a sorcerer adept at casting spells that involve the fury of a storm. The can call into being great storm clouds and summon bolts of lightning to strike down their enemies from the sky. Sorcerers like the mage Daeyin are Storm Mages.
Dwarves, gnomes and true kender may not be storm mages.
!Role Playing:
The Storm Mage finds himself at home in the heart of a great gale, and could not be more comfortable than when he is sitting at home listening to the sound of rain outside his door. They are fascinated by the great sounds of thunder and flashes of lightning.
The Storm Mage's personality reflects that of his passion. Like the storm, he can be calm and bring good to the world (just as a storm bring water to fields), but can turn violent and angry (many have been described as being in a stormy mood) at even the slightest annoyance. Most Storm Mages, though, control their anger, and use it appropriately and quickly. It is a rare Storm Mage that keeps a grudge.
This type of sorcerer typically prefers dark blues and grays (although some flashier ones have been known to wear yellow sashes to symbolize lightning), and often has a "dark" look to him.
!Requirements:
Like the storm, the Storm Mage flows and moves like the air. To reflect this, he must have a minimum Agility of 6. However, since missile weapons rarely work during great storms, the sorcerer have an ability code in Dexterity higher than "C". Though the Storm Mage can be quite strong, he prefers light weapons, especially those that are thin and quick (such as a rapier or stiletto). As such he cannot have an ability code in Strength higher than "C". Such large weapons he finds to bulky for good use. To reflect his sorcery training, the Mage must have an ability code of "A" in Reason. And Due to his Extreme personality, and minimum of 6 in Presence. In addtion, because of unpredictable nature, the Storm Mage must choose his Nature and Demeanor.
|Ability |Score |Code|
|Agility |6 min |-|
|Dexterity |- |C Max|
|Strength |- |C Max|
|Reason |- |A Min|
|Presence |6 min| -|
|Nature & Demeanor| Red Auras only|-|
!Advantages:
Due to his affinity with storms, the Storm Mage gains an automatic trump while casting spells during them, or during any time where winds reach higher than 20mph. He also gains an automatic trump in the school of Aeromancy. Heroes may acquire this role during play.
!Disadvantages
Due to emphasis on storms, the Storm Mage must learn at least one of the following schools: Aeromancy, Electromancy, or Conjuration. But, he may never cast spells from the schools of Geomancy, Pyromancy, or Transmutation.
<<tabs txtMoreTab "Tags" "All Tags" TabAllTags "Miss" "Missing tiddlers" TabMoreMissing "Orph" "Orphaned tiddlers" TabMoreOrphans "Shad" "Shadowed tiddlers" TabMoreShadowed>>
<<allTags excludeLists [a-z]>>
/***
|Name:|TagglyTaggingPlugin|
|Description:|tagglyTagging macro is a replacement for the builtin tagging macro in your ViewTemplate|
|Version:|3.3.1 ($Rev: 9828 $)|
|Date:|$Date: 2009-06-03 21:38:41 +1000 (Wed, 03 Jun 2009) $|
|Source:|http://mptw.tiddlyspot.com/#TagglyTaggingPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License:|http://mptw.tiddlyspot.com/#TheBSDLicense|
!Notes
See http://mptw.tiddlyspot.com/#TagglyTagging
***/
//{{{
merge(String.prototype,{
parseTagExpr: function(debug) {
if (this.trim() == "")
return "(true)";
var anyLogicOp = /(!|&&|\|\||\(|\))/g;
var singleLogicOp = /^(!|&&|\|\||\(|\))$/;
var spaced = this.
// because square brackets in templates are no good
// this means you can use [(With Spaces)] instead of [[With Spaces]]
replace(/\[\(/g," [[").
replace(/\)\]/g,"]] ").
// space things out so we can use readBracketedList. tricky eh?
replace(anyLogicOp," $1 ");
var expr = "";
var tokens = spaced.readBracketedList(false); // false means don't uniq the list. nice one JR!
for (var i=0;i<tokens.length;i++)
if (tokens[i].match(singleLogicOp))
expr += tokens[i];
else
expr += "tiddler.tags.contains('%0')".format([tokens[i].replace(/'/,"\\'")]); // fix single quote bug. still have round bracket bug i think
if (debug)
alert(expr);
return '('+expr+')';
}
});
merge(TiddlyWiki.prototype,{
getTiddlersByTagExpr: function(tagExpr,sortField) {
var result = [];
var expr = tagExpr.parseTagExpr();
store.forEachTiddler(function(title,tiddler) {
if (eval(expr))
result.push(tiddler);
});
if(!sortField)
sortField = "title";
result.sort(function(a,b) {return a[sortField] < b[sortField] ? -1 : (a[sortField] == b[sortField] ? 0 : +1);});
return result;
}
});
config.taggly = {
// for translations
lingo: {
labels: {
asc: "\u2191", // down arrow
desc: "\u2193", // up arrow
title: "title",
modified: "modified",
created: "created",
show: "+",
hide: "-",
normal: "normal",
group: "group",
commas: "commas",
sitemap: "sitemap",
numCols: "cols\u00b1", // plus minus sign
label: "Tagged as '%0':",
exprLabel: "Matching tag expression '%0':",
excerpts: "excerpts",
descr: "descr",
slices: "slices",
contents: "contents",
sliders: "sliders",
noexcerpts: "title only",
noneFound: "(none)"
},
tooltips: {
title: "Click to sort by title",
modified: "Click to sort by modified date",
created: "Click to sort by created date",
show: "Click to show tagging list",
hide: "Click to hide tagging list",
normal: "Click to show a normal ungrouped list",
group: "Click to show list grouped by tag",
sitemap: "Click to show a sitemap style list",
commas: "Click to show a comma separated list",
numCols: "Click to change number of columns",
excerpts: "Click to show excerpts",
descr: "Click to show the description slice",
slices: "Click to show all slices",
contents: "Click to show entire tiddler contents",
sliders: "Click to show tiddler contents in sliders",
noexcerpts: "Click to show entire title only"
},
tooDeepMessage: "* //sitemap too deep...//"
},
config: {
showTaggingCounts: true,
listOpts: {
// the first one will be the default
sortBy: ["title","modified","created"],
sortOrder: ["asc","desc"],
hideState: ["show","hide"],
listMode: ["normal","group","sitemap","commas"],
numCols: ["1","2","3","4","5","6"],
excerpts: ["noexcerpts","excerpts","descr","slices","contents","sliders"]
},
valuePrefix: "taggly.",
excludeTags: ["excludeLists","excludeTagging"],
excerptSize: 50,
excerptMarker: "/%"+"%/",
siteMapDepthLimit: 25
},
getTagglyOpt: function(title,opt) {
var val = store.getValue(title,this.config.valuePrefix+opt);
return val ? val : this.config.listOpts[opt][0];
},
setTagglyOpt: function(title,opt,value) {
// create it silently if it doesn't exist
if (!store.tiddlerExists(title)) {
store.saveTiddler(title,title,config.views.editor.defaultText.format([title]),config.options.txtUserName,new Date(),"");
// <<tagglyTagging expr:"...">> creates a tiddler to store its display settings
// Make those tiddlers less noticeable by tagging as excludeSearch and excludeLists
// Because we don't want to hide real tags, check that they aren't actually tags before doing so
// Also tag them as tagglyExpression for manageability
// (contributed by RA)
if (!store.getTaggedTiddlers(title).length) {
store.setTiddlerTag(title,true,"excludeSearch");
store.setTiddlerTag(title,true,"excludeLists");
store.setTiddlerTag(title,true,"tagglyExpression");
}
}
// if value is default then remove it to save space
return store.setValue(title, this.config.valuePrefix+opt, value == this.config.listOpts[opt][0] ? null : value);
},
getNextValue: function(title,opt) {
var current = this.getTagglyOpt(title,opt);
var pos = this.config.listOpts[opt].indexOf(current);
// supposed to automagically don't let cols cycle up past the number of items
// currently broken in some situations, eg when using an expression
// lets fix it later when we rewrite for jquery
// the columns thing should be jquery table manipulation probably
var limit = (opt == "numCols" ? store.getTaggedTiddlers(title).length : this.config.listOpts[opt].length);
var newPos = (pos + 1) % limit;
return this.config.listOpts[opt][newPos];
},
toggleTagglyOpt: function(title,opt) {
var newVal = this.getNextValue(title,opt);
this.setTagglyOpt(title,opt,newVal);
},
createListControl: function(place,title,type) {
var lingo = config.taggly.lingo;
var label;
var tooltip;
var onclick;
if ((type == "title" || type == "modified" || type == "created")) {
// "special" controls. a little tricky. derived from sortOrder and sortBy
label = lingo.labels[type];
tooltip = lingo.tooltips[type];
if (this.getTagglyOpt(title,"sortBy") == type) {
label += lingo.labels[this.getTagglyOpt(title,"sortOrder")];
onclick = function() {
config.taggly.toggleTagglyOpt(title,"sortOrder");
return false;
}
}
else {
onclick = function() {
config.taggly.setTagglyOpt(title,"sortBy",type);
config.taggly.setTagglyOpt(title,"sortOrder",config.taggly.config.listOpts.sortOrder[0]);
return false;
}
}
}
else {
// "regular" controls, nice and simple
label = lingo.labels[type == "numCols" ? type : this.getNextValue(title,type)];
tooltip = lingo.tooltips[type == "numCols" ? type : this.getNextValue(title,type)];
onclick = function() {
config.taggly.toggleTagglyOpt(title,type);
return false;
}
}
// hide button because commas don't have columns
if (!(this.getTagglyOpt(title,"listMode") == "commas" && type == "numCols"))
createTiddlyButton(place,label,tooltip,onclick,type == "hideState" ? "hidebutton" : "button");
},
makeColumns: function(orig,numCols) {
var listSize = orig.length;
var colSize = listSize/numCols;
var remainder = listSize % numCols;
var upperColsize = colSize;
var lowerColsize = colSize;
if (colSize != Math.floor(colSize)) {
// it's not an exact fit so..
upperColsize = Math.floor(colSize) + 1;
lowerColsize = Math.floor(colSize);
}
var output = [];
var c = 0;
for (var j=0;j<numCols;j++) {
var singleCol = [];
var thisSize = j < remainder ? upperColsize : lowerColsize;
for (var i=0;i<thisSize;i++)
singleCol.push(orig[c++]);
output.push(singleCol);
}
return output;
},
drawTable: function(place,columns,theClass) {
var newTable = createTiddlyElement(place,"table",null,theClass);
var newTbody = createTiddlyElement(newTable,"tbody");
var newTr = createTiddlyElement(newTbody,"tr");
for (var j=0;j<columns.length;j++) {
var colOutput = "";
for (var i=0;i<columns[j].length;i++)
colOutput += columns[j][i];
var newTd = createTiddlyElement(newTr,"td",null,"tagglyTagging"); // todo should not need this class
wikify(colOutput,newTd);
}
return newTable;
},
createTagglyList: function(place,title,isTagExpr) {
switch(this.getTagglyOpt(title,"listMode")) {
case "group": return this.createTagglyListGrouped(place,title,isTagExpr); break;
case "normal": return this.createTagglyListNormal(place,title,false,isTagExpr); break;
case "commas": return this.createTagglyListNormal(place,title,true,isTagExpr); break;
case "sitemap":return this.createTagglyListSiteMap(place,title,isTagExpr); break;
}
},
getTaggingCount: function(title,isTagExpr) {
// thanks to Doug Edmunds
if (this.config.showTaggingCounts) {
var tagCount = config.taggly.getTiddlers(title,'title',isTagExpr).length;
if (tagCount > 0)
return " ("+tagCount+")";
}
return "";
},
getTiddlers: function(titleOrExpr,sortBy,isTagExpr) {
return isTagExpr ? store.getTiddlersByTagExpr(titleOrExpr,sortBy) : store.getTaggedTiddlers(titleOrExpr,sortBy);
},
getExcerpt: function(inTiddlerTitle,title,indent) {
if (!indent)
indent = 1;
var displayMode = this.getTagglyOpt(inTiddlerTitle,"excerpts");
var t = store.getTiddler(title);
if (t && displayMode == "excerpts") {
var text = t.text.replace(/\n/," ");
var marker = text.indexOf(this.config.excerptMarker);
if (marker != -1) {
return " {{excerpt{<nowiki>" + text.substr(0,marker) + "</nowiki>}}}";
}
else if (text.length < this.config.excerptSize) {
return " {{excerpt{<nowiki>" + t.text + "</nowiki>}}}";
}
else {
return " {{excerpt{<nowiki>" + t.text.substr(0,this.config.excerptSize) + "..." + "</nowiki>}}}";
}
}
else if (t && displayMode == "contents") {
return "\n{{contents indent"+indent+"{\n" + t.text + "\n}}}";
}
else if (t && displayMode == "sliders") {
return "<slider slide>\n{{contents{\n" + t.text + "\n}}}\n</slider>";
}
else if (t && displayMode == "descr") {
var descr = store.getTiddlerSlice(title,'Description');
return descr ? " {{excerpt{" + descr + "}}}" : "";
}
else if (t && displayMode == "slices") {
var result = "";
var slices = store.calcAllSlices(title);
for (var s in slices)
result += "|%0|<nowiki>%1</nowiki>|\n".format([s,slices[s]]);
return result ? "\n{{excerpt excerptIndent{\n" + result + "}}}" : "";
}
return "";
},
notHidden: function(t,inTiddler) {
if (typeof t == "string")
t = store.getTiddler(t);
return (!t || !t.tags.containsAny(this.config.excludeTags) ||
(inTiddler && this.config.excludeTags.contains(inTiddler)));
},
// this is for normal and commas mode
createTagglyListNormal: function(place,title,useCommas,isTagExpr) {
var list = config.taggly.getTiddlers(title,this.getTagglyOpt(title,"sortBy"),isTagExpr);
if (this.getTagglyOpt(title,"sortOrder") == "desc")
list = list.reverse();
var output = [];
var first = true;
for (var i=0;i<list.length;i++) {
if (this.notHidden(list[i],title)) {
var countString = this.getTaggingCount(list[i].title);
var excerpt = this.getExcerpt(title,list[i].title);
if (useCommas)
output.push((first ? "" : ", ") + "[[" + list[i].title + "]]" + countString + excerpt);
else
output.push("*[[" + list[i].title + "]]" + countString + excerpt + "\n");
first = false;
}
}
return this.drawTable(place,
this.makeColumns(output,useCommas ? 1 : parseInt(this.getTagglyOpt(title,"numCols"))),
useCommas ? "commas" : "normal");
},
// this is for the "grouped" mode
createTagglyListGrouped: function(place,title,isTagExpr) {
var sortBy = this.getTagglyOpt(title,"sortBy");
var sortOrder = this.getTagglyOpt(title,"sortOrder");
var list = config.taggly.getTiddlers(title,sortBy,isTagExpr);
if (sortOrder == "desc")
list = list.reverse();
var leftOvers = []
for (var i=0;i<list.length;i++)
leftOvers.push(list[i].title);
var allTagsHolder = {};
for (var i=0;i<list.length;i++) {
for (var j=0;j<list[i].tags.length;j++) {
if (list[i].tags[j] != title) { // not this tiddler
if (this.notHidden(list[i].tags[j],title)) {
if (!allTagsHolder[list[i].tags[j]])
allTagsHolder[list[i].tags[j]] = "";
if (this.notHidden(list[i],title)) {
allTagsHolder[list[i].tags[j]] += "**[["+list[i].title+"]]"
+ this.getTaggingCount(list[i].title) + this.getExcerpt(title,list[i].title) + "\n";
leftOvers.setItem(list[i].title,-1); // remove from leftovers. at the end it will contain the leftovers
}
}
}
}
}
var allTags = [];
for (var t in allTagsHolder)
allTags.push(t);
var sortHelper = function(a,b) {
if (a == b) return 0;
if (a < b) return -1;
return 1;
};
allTags.sort(function(a,b) {
var tidA = store.getTiddler(a);
var tidB = store.getTiddler(b);
if (sortBy == "title") return sortHelper(a,b);
else if (!tidA && !tidB) return 0;
else if (!tidA) return -1;
else if (!tidB) return +1;
else return sortHelper(tidA[sortBy],tidB[sortBy]);
});
var leftOverOutput = "";
for (var i=0;i<leftOvers.length;i++)
if (this.notHidden(leftOvers[i],title))
leftOverOutput += "*[["+leftOvers[i]+"]]" + this.getTaggingCount(leftOvers[i]) + this.getExcerpt(title,leftOvers[i]) + "\n";
var output = [];
if (sortOrder == "desc")
allTags.reverse();
else if (leftOverOutput != "")
// leftovers first...
output.push(leftOverOutput);
for (var i=0;i<allTags.length;i++)
if (allTagsHolder[allTags[i]] != "")
output.push("*[["+allTags[i]+"]]" + this.getTaggingCount(allTags[i]) + this.getExcerpt(title,allTags[i]) + "\n" + allTagsHolder[allTags[i]]);
if (sortOrder == "desc" && leftOverOutput != "")
// leftovers last...
output.push(leftOverOutput);
return this.drawTable(place,
this.makeColumns(output,parseInt(this.getTagglyOpt(title,"numCols"))),
"grouped");
},
// used to build site map
treeTraverse: function(title,depth,sortBy,sortOrder,isTagExpr) {
var list = config.taggly.getTiddlers(title,sortBy,isTagExpr);
if (sortOrder == "desc")
list.reverse();
var indent = "";
for (var j=0;j<depth;j++)
indent += "*"
var childOutput = "";
if (depth > this.config.siteMapDepthLimit)
childOutput += indent + this.lingo.tooDeepMessage;
else
for (var i=0;i<list.length;i++)
if (list[i].title != title)
if (this.notHidden(list[i].title,this.config.inTiddler))
childOutput += this.treeTraverse(list[i].title,depth+1,sortBy,sortOrder,false);
if (depth == 0)
return childOutput;
else
return indent + "[["+title+"]]" + this.getTaggingCount(title) + this.getExcerpt(this.config.inTiddler,title,depth) + "\n" + childOutput;
},
// this if for the site map mode
createTagglyListSiteMap: function(place,title,isTagExpr) {
this.config.inTiddler = title; // nasty. should pass it in to traverse probably
var output = this.treeTraverse(title,0,this.getTagglyOpt(title,"sortBy"),this.getTagglyOpt(title,"sortOrder"),isTagExpr);
return this.drawTable(place,
this.makeColumns(output.split(/(?=^\*\[)/m),parseInt(this.getTagglyOpt(title,"numCols"))), // regexp magic
"sitemap"
);
},
macros: {
tagglyTagging: {
handler: function (place,macroName,params,wikifier,paramString,tiddler) {
var parsedParams = paramString.parseParams("tag",null,true);
var refreshContainer = createTiddlyElement(place,"div");
// do some refresh magic to make it keep the list fresh - thanks Saq
refreshContainer.setAttribute("refresh","macro");
refreshContainer.setAttribute("macroName",macroName);
var tag = getParam(parsedParams,"tag");
var expr = getParam(parsedParams,"expr");
if (expr) {
refreshContainer.setAttribute("isTagExpr","true");
refreshContainer.setAttribute("title",expr);
refreshContainer.setAttribute("showEmpty","true");
}
else {
refreshContainer.setAttribute("isTagExpr","false");
if (tag) {
refreshContainer.setAttribute("title",tag);
refreshContainer.setAttribute("showEmpty","true");
}
else {
refreshContainer.setAttribute("title",tiddler.title);
refreshContainer.setAttribute("showEmpty","false");
}
}
this.refresh(refreshContainer);
},
refresh: function(place) {
var title = place.getAttribute("title");
var isTagExpr = place.getAttribute("isTagExpr") == "true";
var showEmpty = place.getAttribute("showEmpty") == "true";
removeChildren(place);
addClass(place,"tagglyTagging");
var countFound = config.taggly.getTiddlers(title,'title',isTagExpr).length
if (countFound > 0 || showEmpty) {
var lingo = config.taggly.lingo;
config.taggly.createListControl(place,title,"hideState");
if (config.taggly.getTagglyOpt(title,"hideState") == "show") {
createTiddlyElement(place,"span",null,"tagglyLabel",
isTagExpr ? lingo.labels.exprLabel.format([title]) : lingo.labels.label.format([title]));
config.taggly.createListControl(place,title,"title");
config.taggly.createListControl(place,title,"modified");
config.taggly.createListControl(place,title,"created");
config.taggly.createListControl(place,title,"listMode");
config.taggly.createListControl(place,title,"excerpts");
config.taggly.createListControl(place,title,"numCols");
config.taggly.createTagglyList(place,title,isTagExpr);
if (countFound == 0 && showEmpty)
createTiddlyElement(place,"div",null,"tagglyNoneFound",lingo.labels.noneFound);
}
}
}
}
},
// todo fix these up a bit
styles: [
"/*{{{*/",
"/* created by TagglyTaggingPlugin */",
".tagglyTagging { padding-top:0.5em; }",
".tagglyTagging li.listTitle { display:none; }",
".tagglyTagging ul {",
" margin-top:0px; padding-top:0.5em; padding-left:2em;",
" margin-bottom:0px; padding-bottom:0px;",
"}",
".tagglyTagging { vertical-align: top; margin:0px; padding:0px; }",
".tagglyTagging table { margin:0px; padding:0px; }",
".tagglyTagging .button { visibility:hidden; margin-left:3px; margin-right:3px; }",
".tagglyTagging .button, .tagglyTagging .hidebutton {",
" color:[[ColorPalette::TertiaryLight]]; font-size:90%;",
" border:0px; padding-left:0.3em;padding-right:0.3em;",
"}",
".tagglyTagging .button:hover, .hidebutton:hover, ",
".tagglyTagging .button:active, .hidebutton:active {",
" border:0px; background:[[ColorPalette::TertiaryPale]]; color:[[ColorPalette::TertiaryDark]];",
"}",
".selected .tagglyTagging .button { visibility:visible; }",
".tagglyTagging .hidebutton { color:[[ColorPalette::Background]]; }",
".selected .tagglyTagging .hidebutton { color:[[ColorPalette::TertiaryLight]] }",
".tagglyLabel { color:[[ColorPalette::TertiaryMid]]; font-size:90%; }",
".tagglyTagging ul {padding-top:0px; padding-bottom:0.5em; margin-left:1em; }",
".tagglyTagging ul ul {list-style-type:disc; margin-left:-1em;}",
".tagglyTagging ul ul li {margin-left:0.5em; }",
".editLabel { font-size:90%; padding-top:0.5em; }",
".tagglyTagging .commas { padding-left:1.8em; }",
"/* not technically tagglytagging but will put them here anyway */",
".tagglyTagged li.listTitle { display:none; }",
".tagglyTagged li { display: inline; font-size:90%; }",
".tagglyTagged ul { margin:0px; padding:0px; }",
".excerpt { color:[[ColorPalette::TertiaryDark]]; }",
".excerptIndent { margin-left:4em; }",
"div.tagglyTagging table,",
"div.tagglyTagging table tr,",
"td.tagglyTagging",
" {border-style:none!important; }",
".tagglyTagging .contents { border-bottom:2px solid [[ColorPalette::TertiaryPale]]; padding:0 1em 1em 0.5em;",
" margin-bottom:0.5em; }",
".tagglyTagging .indent1 { margin-left:3em; }",
".tagglyTagging .indent2 { margin-left:4em; }",
".tagglyTagging .indent3 { margin-left:5em; }",
".tagglyTagging .indent4 { margin-left:6em; }",
".tagglyTagging .indent5 { margin-left:7em; }",
".tagglyTagging .indent6 { margin-left:8em; }",
".tagglyTagging .indent7 { margin-left:9em; }",
".tagglyTagging .indent8 { margin-left:10em; }",
".tagglyTagging .indent9 { margin-left:11em; }",
".tagglyTagging .indent10 { margin-left:12em; }",
".tagglyNoneFound { margin-left:2em; color:[[ColorPalette::TertiaryMid]]; font-size:90%; font-style:italic; }",
"/*}}}*/",
""].join("\n"),
init: function() {
merge(config.macros,this.macros);
config.shadowTiddlers["TagglyTaggingStyles"] = this.styles;
store.addNotification("TagglyTaggingStyles",refreshStyles);
}
};
config.taggly.init();
//}}}
/***
InlineSlidersPlugin
By Saq Imtiaz
http://tw.lewcid.org/sandbox/#InlineSlidersPlugin
// syntax adjusted to not clash with NestedSlidersPlugin
// added + syntax to start open instead of closed
***/
//{{{
config.formatters.unshift( {
name: "inlinesliders",
// match: "\\+\\+\\+\\+|\\<slider",
match: "\\<slider",
// lookaheadRegExp: /(?:\+\+\+\+|<slider) (.*?)(?:>?)\n((?:.|\n)*?)\n(?:====|<\/slider>)/mg,
lookaheadRegExp: /(?:<slider)(\+?) (.*?)(?:>)\n((?:.|\n)*?)\n(?:<\/slider>)/mg,
handler: function(w) {
this.lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = this.lookaheadRegExp.exec(w.source)
if(lookaheadMatch && lookaheadMatch.index == w.matchStart ) {
var btn = createTiddlyButton(w.output,lookaheadMatch[2] + " "+"\u00BB",lookaheadMatch[2],this.onClickSlider,"button sliderButton");
var panel = createTiddlyElement(w.output,"div",null,"sliderPanel");
panel.style.display = (lookaheadMatch[1] == '+' ? "block" : "none");
wikify(lookaheadMatch[3],panel);
w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
}
},
onClickSlider : function(e) {
if(!e) var e = window.event;
var n = this.nextSibling;
n.style.display = (n.style.display=="none") ? "block" : "none";
return false;
}
});
//}}}
Hay ciertas tareas asociadas a combate, que se asignan a ciertos jugadores, ya sea según criterio de los jugadores, o bien del Narrador. Las más frecuentes son:
*[[Líder]]
*[[Explorador]]
*[[Sentinela]]
!Los siguientes son términos que es necesario conocer para entender las reglas del Sistema SAGA
*[[Cartas del Destino]]: Son las 82 cartas que tienen el logo de //Fifth Age// atrás. Juntas se les llama Mazo del Destino o //Fate Deck//.
*''Cartas de Personajes'': Son las 18 cartas de apariencia de cuero marrón, que representan a héroes de la 5ta Era de Krynn.
*[[Héroe]]: un personaje principal en una aventura. Los jugadores siempre juegan el rol de un héroe en los juegos de DragonLance SAGA.
*''Personaje'': Cualquier indivíduo en un escenario de una aventura de DragonLance que no sea un héroe (incluyendo a los monstruos. Pueden ser amigos o enemigos, pero siempre su control y rol es jugado por el Narrador.
*''Escenario'': La historia básica de un juego SAGA. A menudo vienen como aventuras publicadas y vendidas en librerías y tiendas de hobbies, pero jugadores experimentados pueden escribir escenarios originales.
*''Narrador'': Es el jugador que guía a los otros jugadores a través del escenario, jugando el rol de los personajes que conocen. Es el juez final en lo relativo a las reglas de juego.
*[[Habilidades]]: Un par de número y letra que define la habilidad de un personaje (o héroe) en SAGA.
*[[Acciones de Héroes]]: Un intento de un héroe de hacer algo en un escenario, como subir un árbol, nadar, esconderse, atacar o seducir. Las [[Cartas del Destino]] son utilizadas para determinar el éxito o fracaso de las acciones de un héroe, si ésta es realizada en circunstancias que no garantizan su éxito. Cuando el tiempo apremia o existen peligros y amenazas, hasta las acciones más sencillas pueden requerir del uso de las cartas.
*[[Pintas|Pinta de las Cartas del Destino]]: Cada símbolo en las [[Cartas del Destino]] representa cierto tipo de acciones o situaciones. En lugar de ser 4 como en las cartas tradicionales, hay 9 pintas.
*[[Mano]]: es la cantidad de [[Cartas del Destino]] disponibles para el uso por parte de un héroe en sus acciones de juego. Al ejecutar una acción, el jugador (generalmente) escoge de entre las cartas que tiene en mano aquella que será tomada en cuenta para determinar la conclusión de la acción. El tamaño de la Mano (o cantidad de cartas que tiene un jugador) depende de la experiencia o nivel (cantidad de Aventuras) que ha tenido el Héroe. El # de cartas de la Mano puede disminuír a causa de daños ocasionados al Héroe.
*[[Carta de Triunfo]]: Una carta es considerada "de triunfo", cuando la [[Pinta|Pinta de las Cartas del Destino]] está directamente asociada al tipo de acción. Un [[Bono de Triunfo]] garantiza un Triunfo independientemente de la pinta.
The Minotaurs of Krynn are a warlike people. Many of them prefer the blood and gore of battle to the power of the heart. Minotaurs favor battle and honor, and worship the god of vengeance. In ages past, when the gods still graced Krynn, a few select bunch of minotaurs wielded priestly magic. Now, in the Fifth Age, minotaurs of faith have become few and far between. However, some minotaurs have discovered the power of heart helps in battle. Some have even learned how to utilize the advantages of dark mysticism without the moral restraints that bind others.
!Role-playing:
Minotaur necromancers need not be deeply religious to wield the; ower of the heart. Nor are they massive brutal killers. They are still militaristic, and very aggressive. However, on the chain of command, they believe themselves to be somewhere near the top. Minotaur necromancers work for the emperor, and are of elevated status in minotaur society.
Minotaur necromancers are more secretive and subtle than ordinary minotaurs. they like manipulation as opposed to brute force. They would rather send an underling to handle their problems rather then sonffront matters personally.
Minotaur necromancers tend to be more isolationalistic than most most minotaurs, shunning even others of their own kind. while they still believe in the superiority of the minotaur race, they believe that other minotaurs are inferior compared to them.
!Requirements:
This role is intended for mintaur heroes, but it can be used as a template fro heroes of other races. In addition to the normal requirements for minotaurs presented in the Book of the Fifth Age, minotaur necromancers must have at least a "B" code and 7 score in Spirit to attain this role. Also, a minotaur necromancer must master at least the sphere of necromancy. Minotaur necromancers must be dark on the inside to be able to use necromancy to its full extent. Therefore, minotaur necromancers need to have a nature derived from a card whose value is 6 or higher. This role cannot be acquired during play.
!Advantages:
Most minotaurs never get the chance to fully explore the power of the heart. That's why minotuar heroes have a maximum Spirit code of "C". However, minotaur necromancers are the exception to the rule, and are allowed to have a Spirit code of "A" or "B". While other races shunned necromancy, minotaurs embraced it. Minotaur necromancers are given extensive training in the sphere of necromancy. Therefore, any action to cast a spell from the sphere of necromancy warrents a Trump bonus.
!Disadvantages:
Because minotaur necromancers work for the emperor, they owe at least 60 days of direct service to the empire. Now, this doesn't mean that players are "out of play" during those days. After all, the emnperor may send the players on a mission, therefore creating more oppertunities to jump start an adventure. Should a minotaur ever refuse to report back to Mithas, he becomes a renegade. Periodically, the emperor will send mercenarioes and assassins to either drag the minotaur hero back in chains, or kill him. Any minotaur he meets will immediantly be hostile. Should this fate ever befall a hero with this role, he will never enjoy a trump bonus for any Presence action when dealing with other minotaurs, except to resist mysticism. This will also happen if the hero decided to change roles.
/***
|''Name''|TiddlyTagMindMap|
|''Description''|Bring your tiddlers to life in a radial graph which displays all your tiddlywiki tiddlers and the relationships between them. (A bit like The Brain)|
|''Author''|Jon Robson|
|''Contributors''|Nicolas Garcia Belmonte|
|''Version''|1.7|
|''Date''|Nov 2008|
|''Status''|@@experimental@@;|
|''License''|BSD|
|''CoreVersion''|<...>|
|''Documentation''|<...>|
|''Keywords''|data visualisation, mindmap, The Brain, Mind Manager, FreeMind,tag relationships,graph|
|''Dependencies''|Requires the VismoLibraryPlugin tiddler to work|
!Description
Bring your TiddlyWiki to life!
!Notes
To install you will need to paste a line of text into your Theme {{{ <div id="tagmindmap"></div>}}} in the location where you would like to see the visualisation.
Currently we are unable to support this working in internet explorer.. we are working on it however.. sorry! :(
!Usage
{{{
The tagmindmap can be created from a macro call using <<tiddlytagmindmap //params//>>
alternatively paste <div id='tagmindmap'></div> into your page template.
The following macros may be useful however they can be included in the toolbar settings of the tiddlytagmindmap macro.
<<ToggleTagMindMap id>> (create button to toggle mind map with id 'id' on/off)
<<LoadMindMap id>> (create button to load all nodes into mind map with id 'id')
There are a variety of configuration options in the backstage area under tweak. They all begin with TiddlyTagMindMapPlugin:
}}}
!!Parameters
tiddlytagmindmap takes several (but all optional) parameters. Some examples can be seen below, note the order is irrelevant of these parameters.
!!!Animation
You can turn animation on/off by using animate:true or animate:false. By default it is on.
!!!Nodes and Edges
!!!!Directional edges
The directed parameter allows you to add arrowheads to your edges. usage: {{{<< tiddlytagmindmap directed:true>>}}}
!!!!Name Length
nodeNameLength:x where x is an integer will shorten the name of any node with a name longer than x. If x =0, the labels will disappear so you can rely on tooltips.
!!!!Variable node sizes (tagcloud)
notagcloud:true as a parameter will flatten the nodes to have the same size font
!!!Dimensions
{{{<<tiddlytagmindmap height:100 width:100>>}}} will set a tiddlytagmindmap with height and width 100.
!!!Zooming
A parameter zoom allows you to specify an integer representing the initial inflation of the mind map. The smaller it is - the closer the nodes will be together.
{{{<<tiddlytagmindmap zoom:1000>>}}} will give you a very inflated TagMindMap!
!!!Tiddler Pop ups
You can now preview a tiddler by using popup:true
!!!Breadcrumb trail
You can turn visited nodes red when they are clicked on by using the {{{breadcrumb:true}}} parameter by default this is false.
!!!The toolbar
A parameter toolbar is a string of 1s. These signify the buttons. The first digit sets whether the bar should appear vertically or horizontally.
The following digits turn off or on the other available buttons.
!!!!The buttons
The digits preceding the first digit represent these buttons in this order..
toggle, loadall
{{{<<tiddlytagmindmap toolbar:101>>}}} would give you a vertical toolbar with a loadall button
!!!display
display:none
!!!click
click:existing
!!!The Start State
A parameter can be used to specify how the map looks on start up.
Currently the options are empty OR all OR a custom executable javascript function.
The first two options are simple strings eg.
{{{<<tiddlytagmindmap startState:empty>>}}} loads a blank tag mind map however {{{<<tiddlytagmindmap startState:all>>}}} loads all nodes excluding those in the exclude List.
the latter is more interesting. Have a look at [[Example 2]]!
!Revision History
1.6
* can now preview tiddlers in place using popup:true
* can turn off animations using animate:false
* double click opens a node, single click reveals any new nodes and/or performs animations
* fixed mouse panning
1.5 xx/xx
*Ability to add arrow heads to show direction
*better performance
*better control panel: replacement of macros for toggle/zoom in and out with built in toolbar to plugin
*update to new version of RGraph (JIT)
*Ability to set meta-data specific to nodes within a tiddler in optional fields see
http://TiddlyWiki.abego-software.de/#PartTiddlerPlugin (eg. colouring of children/parents/images in node label)
*definable meta data (prefix,suffix,label,color)
*can turn off click function
1.4 11/08 tag cloud integration/multiple tag mind maps/ability to call from macro
1.3 22/10/08 working with ie/packaged up code
!To Do
*bug: zoomin breaks on more than 1 mind map.. no idea why but scale resets :(
*fix ie clicking nodes
*display tiddler loads below the place it;s called from
*Ability to define your own function for relative sizing (ie. you could weight them on some meta field)
*color property should become css property
*ability to resize using %
*distinguish between tags and tiddlers (see CreateNodeJSON - tiddlers that don't exist in store are tagged in data field)
*rss hooks - specify where tags and node names come from in feed
*ability to specify what click function is
*ability to stop displayTiddler from loading into graph (*ability to turn off dynamic as you go updates)
*allow resizing
*auto spread out messy nodes (ie. zoom out if nodes are too close)
*node repositioning and saving of state
*better css support
*performance issues
*deleting edges as tiddlers are deleted
*adapt to parabolic tree mode and other visualisation types
*Self-defined click functions
*Continued code cleanup
*breadcrumbs to become encoded in the node colour (rather than label colour) define a colour of the breadcrumb trail - make it change colour each click (increment colour, so you can get an idea of path you took to get somewhere)
*add pins to locations in the mind map to jump back to (definable in meta data long term, also short term in tiddler edit menu)
!Code
***/
/***
!Layer 1: TiddlyWiki Specific
Jon Robson
***/
{{{
//set descriptions
merge(config.optionsDesc,{
txtTTMM_canvasWidth: "TiddlyTagMindMapPlugin : Width of visualisation. You will need to refresh the page to see the change."
,txtTTMM_canvasHeight: "TiddlyTagMindMapPlugin : Height of visualisation. You will need to refresh the page to see the change."
,txtTTMM_inflation: "TiddlyTagMindMapPlugin : The visualisation can be inflated and deflated to allow you to see the structure from above or close up. This value allows you to set a start inflation."
,txtTTMM_maxNodeNameLength:"TiddlyTagMindMapPlugin : maximum length of a tiddler name. Any tiddlers with names longer than this will be abbrieviated using '...'. Set to zero to make labels disappear altogether and rely completely on tooltips."
,chkTTMM_ignoreLoneNodes: "TiddlyTagMindMapPlugin : any lone tiddlers/nodes (ie. tiddlers that are not tagged with any data) will be ignored in the visualisation. This cleans up the visualisation greatly."
,txtTTMM_excludeNodeList: "TiddlyTagMindMapPlugin :Anything tagged with this will be ignored in the visualisation. Formatted in form ['tiddlername1', 'tiddlername2']"
,chkTTMM_leaveRedBreadCrumbTrail: "TiddlyTagMindMapPlugin : When you visit a node it will be coloured red leaving a breadcrumb trail of where you have been."
}
);
/*MACROS*/
config.macros.TagMindMapCenter = {
handler: function(place,macroName,params,wikifier,paramString,tiddler){
var ttmm = config.macros.tiddlytagmindmap.getAssociatedTiddlyTagMindMapObject(null,false);
ttmm.centerOnNode(params[0]);
}
};
config.macros.TagMindMapEdge={ /* params: node1|commit node2 */
handler: function (place,macroName,params,wikifier,paramString,tiddler) {
var id1 = params[0]; var id2 = params[1];
var ttmm = config.macros.tiddlytagmindmap.getAssociatedTiddlyTagMindMapObject(null,false);
if(!ttmm) return;
if(id1 == "commit") {
this.commit();
return;
}
var name1,name2,data1,data2;
if(id1.id){
//its a json
if(id1.name)name1 = id1.name;
if(id1.data)data1 = id1.data;
id1 = id1.id;
}
if(id2.id){
//its a json
if(id1.name)name2 = id2.name;
if(id2.data)data2 = id2.data;
id2 = id2.id;
}
if(!data1){ data1 = {};}
if(!data2){ data2 = {};}
if(!store.tiddlerExists(id1)){
if(!data1.color && ttmm.settings.emptyTiddlerColor)data1.color = ttmm.settings.emptyTiddlerColor;
data1.emptyTiddler = true;
}
if(!store.tiddlerExists(id2)){
if(!data2.color && ttmm.settings.emptyTiddlerColor)data2.color = ttmm.settings.emptyTiddlerColor;
data2.emptyTiddler = true;
}
if(ttmm){
ttmm.drawEdge(id1,id2,name1,name2,data1,data2);
}
}
,commit: function(){
var ttmm = config.macros.tiddlytagmindmap.getAssociatedTiddlyTagMindMapObject(null,false);
ttmm.computeThenPlot();
}
};
config.macros.LoadMindMap={
label: "loadall",
prompt: "load all tiddlers into the tag mind map",
handler: function (place,macroName,params,wikifier,paramString,tiddler) {
var btn =createTiddlyButton(place,this.label,this.prompt,this.onClick);
if(params[0]){
btn.wrapperID = params[0];
}
}
,onClick: function(e,id)
{
var ttmm;
if(id){
ttmm = config.macros.tiddlytagmindmap.store[id];
}
else{
ttmm = config.macros.tiddlytagmindmap.getAssociatedTiddlyTagMindMapObject(this.wrapperID,true);
}
if(ttmm){
var list = store.getTiddlers();
for (var t=0; t<list.length; t++) {
ttmm.createNodeFromJSON(config.macros.tiddlytagmindmap.createJSON(list[t].title,ttmm));
}
ttmm.computeThenPlot();
}
}
};
config.macros.ToggleTagMindMap={
label: "toggle",
prompt: "Toggle on or off the tag mind map",
handler: function(place,macroName,params,wikifier,paramString,tiddler){
var btn = createTiddlyButton(place,this.label,this.prompt,this.onClick);
if(params[0])btn.wrapperID = params[0];
}
,onClick: function(e){
var id = config.macros.tiddlytagmindmap.getAssociatedTiddlyTagMindMapObject(this.wrapperID,true).wrapper.id;
if(document.getElementById(id).style.display== "none"){
document.getElementById(id).style.display= "";
}
else{
document.getElementById(id).style.display= "none";
}
}
};
config.macros.tiddlytagmindmap={
store: {}, //a library of created ttmm objects
handler: function (place,macroName,params,wikifier,paramString,tiddler) {
if(!place) { //give a default place
place = document.getElementById('tagmindmap');
if(!place) throw "no place to put ttmm!"; //unable to create
paramString =place.getAttribute("parameters");
}
var settings = this.get_ttmm_settings(paramString);
if(settings.display){
settings.toolbar = '010'; //turn toggle button on
}
var elem = this.setup_ttmm_html(place,settings);
try{
this.store[elem.id]= new Tagmindmap(elem,settings);
this.store['last'] = elem.id;
this.store['cur'] = elem.id;
if(settings.startupFunction){
settings.startupFunction(elem.id);
}
if(settings.display){
//alert(":D");
jQuery(".ttmm",place).css({"display":settings.display}); //new
}
}
catch(e){console.log("exception thrown during tiddlytagmindmap creation:"+e);}
},
get_ttmm_setting_defaults: function(){
if(!config.options.txtTTMM_canvasWidth)config.options.txtTTMM_canvasWidth = 800;
if(!config.options.txtTTMM_canvasHeight)config.options.txtTTMM_canvasHeight = 200;
if(!config.options.txtTTMM_inflation)config.options.txtTTMM_inflation = 80;
if(!config.options.txtTTMM_maxNodeNameLength)config.options.txtTTMM_maxNodeNameLength = 25;
if(config.options.chkTTMM_ignoreLoneNodes == null) config.options.chkTTMM_ignoreLoneNodes = false;
if(config.options.chkTTMM_leaveRedBreadCrumbTrail == null) config.options.chkTTMM_leaveRedBreadCrumbTrail = true;
if(!config.options.txtTTMM_excludeNodeList) config.options.txtTTMM_excludeNodeList= ['excludeLists'];
var settings = {};
/*set some defaults based on tweaked preferences if none passed as parameters*/
settings.maxNodeNameLength = config.options.txtTTMM_maxNodeNameLength;
settings.ignoreLoneNodes = config.options.chkTTMM_ignoreLoneNodes;
settings.tagcloud = {off:false};
settings.width = config.options.txtTTMM_canvasWidth;
settings.height =config.options.txtTTMM_canvasHeight;
settings.toolbar = "000";
settings.zoomLevel = parseInt(config.options.txtTTMM_inflation);
settings.breadcrumbs = config.options.chkTTMM_leaveRedBreadCrumbTrail;
settings.animate = true;
var clickfunction = function(node,id,e){
//var tiddlerElem = story.findContainingTiddler(resolveTarget(e));
story.displayTiddler(null, node.id,null,null,null,null,null,id);
};
settings.clickFunction = clickfunction;
return settings;
},
get_ttmm_settings: function(paramString){
var settings = this.get_ttmm_setting_defaults();
var exList = null;
var that = this;
var startupFunction = function(id){};
settings.dynamicUpdateFunction = this.createJSON;
if(paramString){
var prms = paramString.parseParams(null, null, true);
settings.labeldepth = parseInt(getParam(prms, "labeldepth"));
settings.display = getParam(prms,"display"); //new
settings.breadcrumbs = eval(getParam(prms, "breadcrumbs"));
settings.ignoreLoneNodes = eval(getParam(prms, "ignoreLoneNodes"));
settings.arrowheads = eval(getParam(prms, "directed"));
settings.tagcloud.off = eval(getParam(prms, "notagcloud"));
if(getParam(prms,"animate")) settings.animate = eval(getParam(prms,"animate"));
if(getParam(prms, "id")) settings.id = getParam(prms, "id");
if(getParam(prms, "width")) settings.width = getParam(prms, "width");
if(getParam(prms, "height"))settings.height = getParam(prms, "height");
if(getParam(prms, "toolbar")) settings.toolbar= getParam(prms, "toolbar");
if(getParam(prms,"zoom")) settings.zoomLevel = parseInt(getParam(prms,"zoom"));
if(getParam(prms,"maxNodeNameLength"))settings.maxNodeNameLength = getParam(prms,"maxNodeNameLength");
if(getParam(prms, "exclude")) exList = getParam(prms, "exclude");
if(getParam(prms,"displayemptytiddlers"))settings.displayemptytiddlers = getParam(prms,"displayemptytiddlers");
if(getParam(prms,"emptyTiddlerColor")){
settings.emptyTiddlerColor =getParam(prms,"emptyTiddlerColor");
}
var clickfunction;
if(!getParam(prms, "click")){
clickfunction = function(node,id,e){
var tiddlerElem = story.findContainingTiddler(resolveTarget(e));
story.displayTiddler(tiddlerElem, node.id,null,null,null,null,null,id);
return;
};
}
else if(getParam(prms, "click") == "existing") {
clickfunction = function(node,id,e){
if(!node.data.emptyTiddler){
var tiddlerElem = story.findContainingTiddler(resolveTarget(e));
story.displayTiddler(tiddlerElem, node.id,null,null,null,null,null,id);
}
return;
};
}
else if(getParam(prms,"click") == "none"){
clickfunction = function(node,id,e){};
}
settings.clickFunction = clickfunction;
if(getParam(prms,"popup")) {
settings.globalSuffix = function(node){
var place = document.createElement("div");
var tiddler = store.getTiddler(node.id);
if(!tiddler) tiddler = config.shadowTiddlers[node.id];
if(tiddler)createTiddlyPopup(place,"",node.id,tiddler);
return place;
};
}
var startState = getParam(prms, "startState");
if(startState){
if(startState == 'all')
startupFunction = function(id){
config.macros.LoadMindMap.onClick(null,id);
}
else if(startState == 'empty'){
startupFunction = function(id){
};
}
/*else if(startState == 'default'){
startupFunction = function(id){
con
var startState = store.filterTiddlers(store.getTiddlerText("DefaultTiddlers"));
that.loadTiddlersIntoTTMM(startState,id);
}
}*/
else{//parse as a list of tiddler names
if(startState){
startupFunction = function(id){
if(startState.length == 0) return;
that.loadTiddlersIntoTTMM(startState,id);
}
}
}
var focus = getParam(prms,"focus");
var onstartup = function(id){
var ttmm = config.macros.tiddlytagmindmap.store[id];
startupFunction(id);
if(focus){
ttmm.centerOnNode(focus);
}
}
settings.startupFunction = onstartup;
}
}
if(!exList){
exList = [];
if(config.options.txtTTMM_excludeNodeList)exList = config.options.txtTTMM_excludeNodeList;
}
/*set the excluded nodes */
var l = eval(exList);
settings.excludeNodeList = [];
for(var i=0; i < l.length; i++){
settings.excludeNodeList.push(l[i]);
settings.excludeNodeList = settings.excludeNodeList.concat(getChildren(l[i]));
}
return settings;
}
,setup_ttmm_html: function(place,settings){
if(place.id == 'tagmindmap')settings.id = 'default';
if(place.style.width) settings.width = place.style.width;
if(place.style.height) settings.height = place.style.height;
/*setup tag mind map */
var newTTMM = document.createElement("div");
if(!settings.id) settings.id="ttmm_" +Math.random();
newTTMM.id = settings.id;
newTTMM.style.width = settings.width +"px";
newTTMM.style.height= settings.height +"px";
newTTMM.setAttribute("class","ttmm");
/*setup toolbar */
var toolbar = document.createElement("div");
toolbar.setAttribute("class","ttmm_toolbar");
var html="", divider = " ";
if(settings.toolbar[0] == 1){//MAKE VERTICAL
toolbar.style.height = "1px";
toolbar.style.position = "relative";
var temp = parseInt(settings.width) +10;
toolbar.style.top = "0px";
toolbar.style.left = temp+"px";
divider = "\n";
}
if(settings.toolbar[1] == 1) html += "<<ToggleTagMindMap " + newTTMM.id+">>" + divider;
if(settings.toolbar[2] == 1) html += "<<LoadMindMap " + newTTMM.id+">>"+ divider;
place.appendChild(toolbar);
wikify(html,toolbar);
place.appendChild(newTTMM);
if(!document.getElementById(this.store['first']))this.store['first'] = newTTMM.id; //no primary ttmm exists
if(!newTTMM.style.width) newTTMM.style.width = settings.width;
if(!newTTMM.style.height) newTTMM.style.height = settings.height;
return newTTMM;
}
,loadTiddlersIntoTTMM: function(tiddlerList,visualisationID){
var viz;
if(!visualisationID)
viz = this.store[this.store['first']];
else
viz = this.store[visualisationID];
var nodesLoaded = false;
var title ="";var firstTitle="";
for(var i =0; i < tiddlerList.length; i++){
if(tiddlerList[i].title) title = tiddlerList[i].title;
else title = tiddlerList[i];
if(i==0) firstTitle = title;
nodesLoaded = viz.createNodeFromJSON(this.createJSON(title,viz)) | nodesLoaded;
}
if(viz.rgraph){
if(nodesLoaded !=0){
viz.rgraph.compute();
viz.rgraph.plot();
}
viz.centerOnNode(title);
}
}
,getAssociatedTiddlyTagMindMapObject: function(id,getFirstCreatedTTMM){
if(id) return this.store[id];
else {
if(getFirstCreatedTTMM)
return this.store[this.store['first']];
else
return this.store[this.store['last']];
}
}
,_createJSONTagMindMapNodes: function(mylist,storeElement) {
var res=[];
for (var t=0; t<mylist.length; t++){
var node =mylist[t];
res.push(config.macros.tiddlytagmindmap._createJSONTagMindMapNode(node,storeElement));
}
return res;
}
,_createJSONTagMindMapNode: function(id,storeElement){
var json = {};
json.id = id;
json.name = id;
nodeData = {};
var parents = getParents(id);
for(var i=0; i < parents.length; i++){
var nodeid = parents[i];
if(store.tiddlerExists(nodeid)){
var tiddler = store.getTiddler(nodeid);
if(tiddler.fields.childrencolor) nodeData.color = tiddler.fields.childrencolor;
}
}
var children = getChildren(id);
for(var i=0; i < children.length; i++){
var nodeid = children[i];
if(store.tiddlerExists(nodeid)){
var tiddler = store.getTiddler(nodeid);
if(tiddler.fields.parentcolor) nodeData.color = tiddler.fields.parentcolor;
}
}
if(store.tiddlerExists(id)){
var tiddler = store.getTiddler(id);
if(tiddler.fields.nodecolor) nodeData.color = tiddler.fields.nodecolor;
if(tiddler.fields.nodeprefix) {
var place =createTiddlyElement(null,"div");
wikify(tiddler.fields.nodeprefix,place);
nodeData.nodeLabelPrefix = place;
}
if(tiddler.fields.nodesuffix) {
var place =createTiddlyElement(null,"div");
wikify(tiddler.fields.nodesuffix,place);
nodeData.nodeLabelSuffix = place;
}
if(tiddler.fields.nodelabel) {
var place =createTiddlyElement(null,"div");
wikify(tiddler.fields.nodelabel,place);
nodeData.label = place;
}
if(tiddler.fields.nodetooltip) {nodeData.title = tiddler.fields.nodetooltip;}
}
if(!nodeData.color){
var empty = false;
if(!store.tiddlerExists(id) && !store.isShadowTiddler(id)){
empty = true;
}
if(store.tiddlerExists(id)){
var tiddler = store.getTiddler(id);
if(tiddler.text == null || tiddler.text == "") empty =true;
}
if(empty){
nodeData.emptyTiddler = true;
//nodeData.color = "#cccccc";
//console.log(storeElement.settings);
if(storeElement && storeElement.settings.emptyTiddlerColor) nodeData.color= storeElement.settings.emptyTiddlerColor;
//storeElement
}
}
if(nodeData){
json.data =nodeData;
}
return json;
}
,createJSON: function(nodeid,storeElement){
if(!nodeid) return "{}";
var myjson = {};
var children = getChildren(nodeid);
var parents = getParents(nodeid);
myjson.children = config.macros.tiddlytagmindmap._createJSONTagMindMapNodes(children,storeElement);
myjson.parents = config.macros.tiddlytagmindmap._createJSONTagMindMapNodes(parents,storeElement);
myjson.node = config.macros.tiddlytagmindmap._createJSONTagMindMapNode(nodeid,storeElement);
return myjson;
}
};
function getParents(a){
if(store.getTiddler(a)){
return store.getTiddler(a).tags;
}
else
return [];
}
function getChildren(a){
if(store.getTaggedTiddlers(a)){
var tags = store.getTaggedTiddlers(a);
if(tags.length == 0) return [];
var a = new Array();
for (var t=0; t<tags.length; t++) {
a.push(tags[t].title);
}
return a;
}
else
return [];
}
story.beforettmm_displayTiddler = story.displayTiddler;
story.displayTiddler = function(srcElement,tiddler,template,animate,unused,customFields,toggle,visualisationID)
{
try{
if(!document.getElementById(config.macros.tiddlytagmindmap.store['first'])) {
config.macros.tiddlytagmindmap.handler(); //try and setup a default one
}
}
catch(e){
};
var title = (tiddler instanceof Tiddler)? tiddler.title : tiddler;
if(config.macros.tiddlytagmindmap.store){
try{
if(!visualisationID && config.macros.tiddlytagmindmap.store['first']) { //call came from outside tagmindmap
visualisationID =config.macros.tiddlytagmindmap.store['first'];
}
if(visualisationID){
res = config.macros.tiddlytagmindmap.loadTiddlersIntoTTMM([title],visualisationID);
}
}
catch(e){
//console.log("exception in display tiddler for "+title+" in visualisation" + visualisationID +": " + e);
}
}
story.beforettmm_displayTiddler(srcElement,tiddler,template,animate,unused,customFields,toggle);
};
}}}
/***
296.56
58 * 151.46
246.56
!Layer 2: DynamicInteract: Extension of RGraph
***/
{{{
Array.prototype.contains = function(item)
{
return this.indexOf(item) != -1;
};
if(!Array.indexOf) {
Array.prototype.indexOf = function(item,from)
{
if(!from)
from = 0;
for(var i=from; i<this.length; i++) {
if(this[i] === item)
return i;
}
return -1;
};
}
var Tagmindmap = function(wrapper,settings){
if(settings.clickFunction)
this.callWhenClickOnNode = settings.clickFunction;
else
this.callWhenClickOnNode = function(node,id){return};
if(settings.dynamicUpdateFunction)
this.dynamicUpdateFunction = settings.dynamicUpdateFunction;
else
this.dynamicUpdateFunction = function(node,id){return {};};
this.wrapper = wrapper;
this._setup(settings);
//this._init_html_elements(wrapper.id);
this._init_html_elements();
var that = this;
var handler = function(t){
that.transform(t);
}
var controls = ["pan","zoom"];
if(!config.browser.isIE) controls.push("mousepanning");
this.controlpanel =new VismoController(wrapper,{handler:handler,controls:controls});//
this.ready = false;
this.children = {};
this.parents = {};
this.ready = true;
this.controlpanel.setTransformation({translate:{x:0,y:0}, scale:{x: this.settings.zoomLevel,y: this.settings.zoomLevel}});
};
Tagmindmap.prototype = {
transform: function(t){
var compute = false;
if(this.settings.zoomLevel != t.scale.x) {
t.translate.x = 0; t.translate.y = 0;
if(this.lastclickednode) this.rgraph.root = this.lastclickednode;
if(t.scale.x > 0){
this.settings.zoomLevel = parseFloat(t.scale.x);
}
compute = true;
}
if(this.rgraph){
var c= {x:t.translate.x * t.scale.x, y:t.translate.y* t.scale.y};
this.rgraph.offsetCenter(c.x,c.y);
if(compute) this.rgraph.compute();
this.rgraph.plot();
}
},
_setup: function(settings){
this.settings = {'animate':true,'arrowheads':false,'maxNodeNameLength':99999,'breadcrumbs': true,'lineColor':'#ccddee','nodeColor':'#ccddee','zoomLevel':100, 'ignoreLoneNodes':false,'excludeNodeList': ['excludeLists']}; //put all default settings here
this.settings.tagcloud = {'smallest': 0.8, 'largest': 1.8, 'upper':0, 'off': false}; //upper is the maximum sized node
this.settings.labeldepth = false;
this.graph_showCirclesFlag = false; //shows circles in the mind map
this.maxNodeNameLength = 0;
this.displacement = {'x':0, 'y':0};
this.maxChildrenOnSingleNode = 0;
this.thehiddenbridge = "RGRAPHTREEBRIDGE"; //a hidden node which bridges all dislocated nodes.
this.settings.breadcrumb_startcolor = "red"; //rgb(0,0,0)
/*above defaults below read in */
for(var i in settings){
this.settings[i] = settings[i];
}
this.settings.arrowheads = settings.arrowheads;
this.settings.breadcrumbs = settings.breadcrumbs;
this.settings.tagcloud.off = settings.tagcloud.off;
this.settings.excludeNodeList = settings.excludeNodeList;
this.settings.ignoreLoneNodes = settings.ignoreLoneNodes;
this.maxNodeNameLength = settings.maxNodeNameLength;
this.settings.zoomLevel = settings.zoomLevel;
var ttmm = this;
},
_init_html_elements: function(){
var wrapperID = this.wrapper.id;
if(!document.getElementById(wrapperID)){ throw (wrapperID + " html element doesn't exist");}
var canvasID = wrapperID + "_canvas"; //the canvas object ID
this.labelContainer = wrapperID + "_label_container";
this.nodeLabelPrefix = canvasID +"_";
/*setup the divs */
var wrapper = this.wrapper;
wrapper.style.position = "relative";
if(!wrapper.style.height){wrapper.style.height = "200px";}
if(!wrapper.style.width){wrapper.style.width = "200px";}
var labelContainer = document.createElement("div");
labelContainer.id=this.labelContainer;
labelContainer.style.position= 'relative';
var canvas = document.createElement("canvas");
canvas.id = canvasID;
canvas.width = parseInt(wrapper.style.width);
canvas.height =parseInt(wrapper.style.height);
wrapper.appendChild(labelContainer);
wrapper.appendChild(canvas);
this.canvas = canvas;
if(config.browser.isIE && G_vmlCanvasManager) {G_vmlCanvasManager.init_(document);} //ie hack - needs changing to work outside tw
},
createNodeFromJSON: function(json){
//console.log("ici");
if(!json || json == {}) return;
var temp = false;
var res = false;
var node1= json['node'];
if(json['parents']){
for(var i=0; i < json['parents'].length; i++){
var parent = json['parents'][i];
temp = this.drawEdge(parent['id'],node1['id'],parent['name'],node1['name'],parent['data'],node1['data']);
res = temp | res;
}
}
if(json['children']){
for(var i=0; i < json['children'].length; i++){
var child = json['children'][i];
temp = this.drawEdge(node1['id'],child['id'],node1['name'],child['name'],node1['data'],child['data']);
res = temp | res;
}
}
if(json['children'] && json['parents']){
if(!this.settings.ignoreLoneNodes && json['children'].length ==0 && json['parents'].length == 0)
temp = this.drawEdge(this.thehiddenbridge, node1['id'],null,node1['name'],null,node1['data']);
res = temp | res;
}
//console.log("done");
return res;
},
centerOnNode:function(id){
var t = this.controlpanel.getTransformation();
t.translate= {x:0,y:0};
this.controlpanel.setTransformation(t);
try{
this.rgraph.onClick(id);
//console.log("good");
}
catch(e){
var ttmm = this;
var f = function(){
ttmm.centerOnNode(id);
};
window.setTimeout(f,100);
}
},
getCurrentNodeID: function(){
if(!this.rgraph.graph.root) return false;
if(this.rgraph.graph.root.id == this.thehiddenbridge) return false;
else return this.rgraph.graph.root.id;
},
setNodeName: function(nodeid,newName){
var node = this.controller.getNode(nodeid);
if(node.name != newName){
node.name = newName;
if(this.thehiddenbridge != nodeid && this.graph_index) this.graph_index[newName] = nodeid;
}
},
mergeNodeData: function(id,data){
var node = this.controller.getNode(id);
if(!node) return;
for (var key in data){
if(typeof node.data[key] == 'array')
node.data[key] = node.data[key].concat(data[key]);
else
node.data[key] = data[key];
}
if(node.data.weight > this.settings.tagcloud.upper) {
this.settings.tagcloud.upper = node.data.weight;
}
},
setNodeData: function(id,data,newvalue){
var node = this.controller.getNode(id);
if(!node) return;
if(!newvalue){
node.data = data;
}
else{
node.data[data] = newvalue;
}
if(node.data.weight > this.settings.tagcloud.upper) {
this.settings.tagcloud.upper = node.data.weight;
}
},
_nodeInExcludeList: function(id){
return this.settings.excludeNodeList.contains(id);
},
drawEdge: function(id_a,id_b,name_a,name_b,data_a,data_b){
if(this._nodeInExcludeList(id_a) || this._nodeInExcludeList(id_b)) return false;
plotNeeded=false;
if(id_a != "" && id_b != ""){
plotNeeded = this._make_connection(id_a,id_b);
if(name_a){this.setNodeName(id_a,name_a);}
if(name_b){this.setNodeName(id_b,name_b);}
if(data_a) {this.mergeNodeData(id_a,data_a); }
if(data_b) {this.mergeNodeData(id_b,data_b);}
}
return plotNeeded;
},
_make_connection: function(a,b){
var drawn = this._setupMapIfNeeded(a);
//console.log("ici mc");
var node1, node2;
node1 = this.controller.getNode(a);
node2 = this.controller.getNode(b);
if(node1 && node2){
if(node1.adjacentTo(node2)) {return false;}
}
else if(!node1 && !node2) {//neither in graph yet
drawn = this._make_connection(this.thehiddenbridge,a); //if neither node is currently in tree, then we need to create a "bridge" to connect the trees
}
if(!node1) {node1= new Graph.Node(a,a,{});drawn= true; }//create this node
if(!node2) {node2= new Graph.Node(b,b,{});drawn= true; }//create that node
if(node1){
if(!node1.adjacentTo(node2)){
this.controller.addAdjacence(node1,node2);
node1 = this.controller.getNode(a);
node2 = this.controller.getNode(b);
if(!this.children[a]) this.children[a] = [];
if(!this.parents[b]) this.parents[b] = [];
this.children[a].push(b);
this.parents[b].push(a);
//console.log("made connection");
return true;
}
}
},
deleteNode: function(id){
var node = this.rgraph.controller.getNode(id);
//console.log("start",node,"end");
var parents = node.data.parents;
var children = node.data.children;
//console.log(id,parents,children);
if(children){
//sort out children
for(var i=0; i < children.length; i++){
var childNode = this.rgraph.controller.getNode(children[i]);
var oldparents = childNode.data.parents;
var newparents = [];
for(var j=0; j < oldparents.length; j++){
if(oldparents[j] != id)newparents.push(oldparents[j]);
}
this.setNodeData(children[i],"parents",newparents);
if(newparents.length == 0) { //connect it up to the bridge
this.drawEdge(this.thehiddenbridge,children[i]);
}
}
}
//sort out parents
if(parents){
for(var i=0; i < parents.length; i++){
if(parents[i] != this.thehiddenbridge){
var parentNode = this.rgraph.controller.getNode(parents[i]);
var oldchildren = parentNode.data.children;
var newchildren = [];
for(var j=0; j < oldchildren.length; j++){
if(oldchildren[j] != id)newchildren.push(oldchildren[j]);
}
this.setNodeData(parents[i],"children",newchildren);
}
}
}
this.rgraph.controller.removeNode(id);
},
computeThenPlot: function(){
try{
this.rgraph.compute();
this.rgraph.plot();
}
catch(e){
var ttmm = this;
var f = function(){
ttmm.computeThenPlot();
};
window.setTimeout(f,100);
//console.log(e+"in computeThenPlot");
}
},
_trimNodeName: function(node_name){
if(this.maxNodeNameLength ==0) return "<span> </span>";
if(this.maxNodeNameLength){
var nlength = this.maxNodeNameLength;
if(node_name.length > nlength)
return node_name.substr(0,nlength/2) + "..." + node_name.substr(node_name.length-nlength/2,node_name.length);
else
return node_name;
}
return node_name;
},
_getController: function(){
var ttmm = this;
var effectHash = {};
var controller = {
removeNode: function(id){
var el = document.getElementById(this.getNodeLabelPrefix()+id);
el.parentNode.removeChild(el);
var graph = ttmm.rgraph.graph;
if(graph) graph.removeNode(id);
},
getNode: function(id){
var n = GraphUtil.getNode(ttmm.rgraph.graph,id);
return n;
},
addAdjacence: function(node1,node2){
ttmm.rgraph.graph.addAdjacence(node1,node2);
},
/*some custom defined controller operations (search in RGraph source)*/
getZoomLevel: function(){
return parseFloat(ttmm.settings.zoomLevel);
},
setOffset: function(d){ttmm.displacement = d;},
getOffset: function(){return ttmm.displacement;},
getNodeLabelContainer: function(){
return ttmm.labelContainer;
},
getNodeLabelPrefix: function(){return ttmm.nodeLabelPrefix;},
onBeforeCompute: function(node) {
ttmm.createNodeFromJSON(ttmm.dynamicUpdateFunction(node.id));
if(ttmm.settings.breadcrumbs) {
ttmm.setNodeData(node.id,"color",ttmm.settings.breadcrumb_startcolor);
}
},
getName: function(node1, node2) {
for(var i=0; i<node1.data.length; i++) {
var dataset = node1.data[i];
if(dataset.key == node2.name) return dataset.value;
}
for(var i=0; i<node2.data.length; i++) {
var dataset = node2.data[i];
if(dataset.key == node1.name) return dataset.value;
}
},
onCreateLabel: function(domElement, node) {
var depth = node._depth;
if(!ttmm.rgraph || !ttmm.rgraph.graph || !ttmm.rgraph.graph.root) return;
var depth2 = ttmm.rgraph.graph.root._depth;
}
,onBeforeCompute: function(){
var i;
var nodes =ttmm.rgraph.graph.nodes;
var total = 0;
for(i in nodes){
var node = nodes[i];
if(node.data.weight){
var weight =node.data.weight;
if(weight > ttmm.settings.tagcloud.upper)ttmm.settings.tagcloud.upper = weight;
}
}
}
,attachClickFunction: function(domElement,node){
if(node.id == this.thehiddenbridge) return;
var dblclickfunction = function(event){
ttmm.callWhenClickOnNode(node,ttmm.wrapper.id,event);
};
var clickfunction = function(event){
if(ttmm.rgraph.getRoot() == node) {
dblclickfunction(event);
return;}
ttmm.createNodeFromJSON(ttmm.dynamicUpdateFunction(node.id));
ttmm.centerOnNode(node.id);
};
jQuery(domElement).mouseup(clickfunction);
}
,getMaxChildren: function(){
var max =0,num;
for(var i in ttmm.children){
if(ttmm.children[i])
num = ttmm.children[i].length;
else
num =0;
if(num > max) max = num;
}
return max;
},
calculateNodeWeight: function(node){
var weight=0, u=0;
if(node.data.weight) { //user has defined some sort of weight
weight = parseFloat(node.data.weight);
u =parseFloat(ttmm.settings.tagcloud.upper);
}
else{ //just take number of children
if(ttmm.children[node.id]){
weight = ttmm.children[node.id].length;
}
u = this.getMaxChildren();
}
var s,l;
if(ttmm.settings.tagcloud.smallest){
s = parseFloat(ttmm.settings.tagcloud.smallest);
}
else{
s = 0.5;
}
if(ttmm.settings.tagcloud.largest) {
l =parseFloat(ttmm.settings.tagcloud.largest);
}
else{
l = 2;
}
var fontsize = s + ((l - s) * parseFloat(weight / u));
//console.log(s,l,weight,u,fontsize);
return fontsize;
},
onPlaceLabel: function(domElement, node) {
if(ttmm.settings.labeldepth && ttmm.rgraph && node._depth){
if(node._depth > ttmm.settings.labeldepth) return;
}
domElement.innerHTML = ""; //quick and dirty flush
if(node.id != ttmm.thehiddenbridge){
if(node.data.color) domElement.style.color = node.data.color;
if(node.data.title){
domElement.title = node.data.title;
}
else{
domElement.title = node.name;
}
var prefix, nodeLabel,suffix;
if(node.data.nodeLabelPrefix) prefix =node.data.nodeLabelPrefix;
if(prefix){
prefix.setAttribute("class","nodeLabelPrefix");
domElement.appendChild(prefix);
}
if(!node.data.label){
nodeLabel = document.createElement("span");
var labelText = ttmm._trimNodeName(node.name);
nodeLabel.appendChild(document.createTextNode(labelText));
}
else{
nodeLabel = node.data.label;
}
if(!ttmm.settings.tagcloud.off){
var fontsize = this.calculateNodeWeight(node);
nodeLabel.style.fontSize = fontsize + "em";
}
var classdef ="nodeLabel";
if(ttmm.rgraph.getRoot() == node){
classdef += " active";
}
nodeLabel.setAttribute("class",classdef);
this.attachClickFunction(nodeLabel,node);
domElement.appendChild(nodeLabel);
if(ttmm.settings.globalSuffix){
suffix =ttmm.settings.globalSuffix(node);
suffix.setAttribute("class","nodeLabelSuffix");
domElement.appendChild(suffix);
}
if(node.data.nodeLabelSuffix) {
suffix =node.data.nodeLabelSuffix;
suffix.setAttribute("class","nodeLabelSuffix");
domElement.appendChild(suffix);
}
}
else domElement.style.display = "none";
var left = parseInt(domElement.style.left);
domElement.style.width = '';
domElement.style.height = '';
var w = domElement.offsetWidth;
domElement.style.left = (left - w /2) + 'px';
},
onAfterCompute: function() {
if(ttmm._afterComputeFunction){
ttmm._afterComputeFunction();
ttmm._afterComputeFunction = false;
}
},
onBeforePlotLine: function(adj){
lineW = ttmm.canvas.getContext().lineWidth;
nodeid = adj.nodeFrom.id;
nodeid2 = adj.nodeTo.id;
if(nodeid == ttmm.thehiddenbridge || nodeid2 == ttmm.thehiddenbridge){
ttmm.canvas.getContext().lineWidth = "0";
}
else ttmm.canvas.getContext().lineWidth = "1";
},
onAfterPlotLine: function(adj){
var l =this.getNodeLabelContainer();
//document.getElementById(l).innerHTML = "";
var context = ttmm.canvas.getContext();
var canvas = ttmm.canvas;
var node = adj.nodeFrom, child = adj.nodeTo;
var pos = node.pos.toComplex();
var posChild = child.pos.toComplex();
var d = this.getOffset();//jon
//draw arrowhead.. (angle needs to be calculated)
if(ttmm.settings.arrowheads){
if(node.id == ttmm.thehiddenbridge)return;
//console.log("arrowhead from",node.id, "to",child.id)
canvas.path('stroke', function(context) {
var r = 20;
var ctx = context;
ctx.save();
//ctx.beginPath();
ctx.translate(posChild.x +d.x,posChild.y+d.y);
var o = parseFloat(posChild.y-pos.y);
var a = parseFloat(posChild.x -pos.x);
if(a !=0){
var rad = Math.atan2(o,a);
ctx.rotate(rad);
ctx.moveTo(2,0);
ctx.lineTo(-r,-4);
ctx.lineTo(-r,4);
ctx.lineTo(2,0);
ctx.fill();
}
ctx.restore();
});
}
ttmm.canvas.getContext().lineWidth = "1";
}
};
return controller;
},
_setupMapIfNeeded: function(lastOpenNode){
//console.log("Trying to setup map");
if(!this.canvas){
this._init_html_elements();
}
var ctx = this.canvas.getContext;
if(!ctx) {console.log("no context available! Please install ExplorerCanvas");}
if(this.graphloaded) return false;
this.graphloaded = true;
//this._firstnode =lastOpenNode;
var json = {"id":this.thehiddenbridge,"children":[{"id":lastOpenNode,"name":lastOpenNode, "data":{"parents":[this.thehiddenbridge], "children":[]}, "children":[]}], 'data':{"parents":[], "children":[lastOpenNode]}};
json.data = {};
json.data.nodraw=true;
this.canvas= new Canvas(this.canvas.id, this.settings.nodeColor, this.settings.lineColor);
controller = this._getController();
this.rgraph= new RGraph(this.canvas, controller,this.labelContainer);
Config['drawConcentricCircles'] = this.graph_showCirclesFlag;
this.rgraph.loadTreeFromJSON(json);
this.controller = controller;
this.rgraph.compute();
this.centerOnNode(lastOpenNode);
//this.rgraph.graph.root = this.controller.getNode(lastOpenNode);
//if(!this.rgraph.graph.root) this.rgraph.graph.root =this.controller.getNode(this._firstNode);
return true;
}
};
}}}
/*
* File: RGraph.js
*
* Author: Nicolas Garcia Belmonte
*
* Copyright: Copyright 2008 by Nicolas Garcia Belmonte.
*
* Homepage: <http://thejit.org>
*
* Version: 1.0.7a
*
* License: BSD License
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the organization nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY Nicolas Garcia Belmonte ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL Nicolas Garcia Belmonte BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/*
Object: $_
Provides some common utility functions.
*/
var $_ = {
fn: function() { return function() {}; },
merge: function(){
var mix = {};
for (var i = 0, l = arguments.length; i < l; i++){
var object = arguments[i];
if (typeof object != 'object') continue;
for (var key in object){
var op = object[key], mp = mix[key];
mix[key] = (mp && typeof op == 'object' && typeof mp == 'object') ? this.merge(mp, op) : this.unlink(op);
}
}
return mix;
},
unlink: function (object){
var unlinked = null;
if(this.isArray(object)) {
unlinked = [];
for (var i = 0, l = object.length; i < l; i++) unlinked[i] = this.unlink(object[i]);
} else if(this.isObject(object)) {
unlinked = {};
for (var p in object) unlinked[p] = this.unlink(object[p]);
} else return object;
return unlinked;
},
isArray: function(obj) {
return obj.constructor.toString().match(/array/i);
},
isString: function(obj) {
return obj.constructor.toString().match(/string/i);
},
isObject: function(obj) {
return obj.constructor.toString().match(/object/i);
}
} ;
/*
Class: Canvas
A multi-purpose Canvas object decorator.
*/
/*
Constructor: Canvas
Canvas initializer.
Parameters:
canvasId - The canvas tag id.
fillStyle - (optional) fill color style. Default's to black
strokeStyle - (optional) stroke color style. Default's to black
Returns:
A new Canvas instance.
*/
var Canvas= function (canvasId, fillStyle, strokeStyle) {
//browser supports canvas element
this.canvasId= canvasId;
this.fillStyle = fillStyle;
this.strokeStyle = strokeStyle;
//canvas element exists
if((this.canvas= document.getElementById(this.canvasId))
&& this.canvas.getContext) {
this.ctx = this.canvas.getContext('2d');
this.ctx.fillStyle = fillStyle || 'black';
this.ctx.strokeStyle = strokeStyle || 'white';
this.setPosition();
this.translateToCenter();
} else {
throw "Canvas object could not initialize.";
}
};
Canvas.prototype= {
/*
Method: getContext
Returns:
Canvas context handler.
*/
getContext: function () {
return this.ctx;
},
/*
Method: setPosition
Calculates canvas absolute position on HTML document.
*/
setPosition: function() {
var obj= this.canvas;
var curleft = curtop = 0;
if (obj.offsetParent) {
curleft = obj.offsetLeft
curtop = obj.offsetTop
while (obj = obj.offsetParent) {
curleft += obj.offsetLeft
curtop += obj.offsetTop
}
}
this.position= { x: curleft, y: curtop };
},
/*
Method: getPosition
Returns:
Canvas absolute position to the HTML document.
*/
getPosition: function() {
return this.position;
},
/*
Method: clear
Clears the canvas object.
*/
clear: function () {
this.ctx.clearRect(-this.getSize().x / 2, -this.getSize().x / 2, this.getSize().x, this.getSize().x);
},
/*
Method: drawConcentricCircles
Draws concentric circles. Receives an integer specifying the number of concentric circles.
*/
drawConcentricCircles: function (elem) {
var config = Config;
var times = elem || 6;
var c = this.ctx;
c.strokeStyle = config.concentricCirclesColor;
var pi2 = Math.PI*2;
for(var i=1; i<=times; i++) {
c.beginPath();
c.arc(0, 0, (i*config.levelDistance), 0, pi2, true);
c.stroke();
c.closePath();
}
c.strokeStyle = this.strokeStyle;
},
/*
Method: translateToCenter
Translates canvas coordinates system to the center of the canvas object.
*/
translateToCenter: function() {
this.ctx.translate(this.canvas.width / 2, this.canvas.height / 2);
},
/*
Method: getSize
Returns:
An object that contains the canvas width and height.
i.e. { x: canvasWidth, y: canvasHeight }
*/
getSize: function () {
var width = this.canvas.width;
var height = this.canvas.height;
return { x: width, y: height };
},
/*
Method: path
Performs a _beginPath_ executes _action_ doing then a _type_ ('fill' or 'stroke') and closing the path with closePath.
*/
path: function(type, action) {
this.ctx.beginPath();
action(this.ctx);
this.ctx[type]();
this.ctx.closePath();
}
};
/*
Class: Complex
A multi-purpose Complex Class with common methods.
*/
/*
Constructor: Complex
Complex constructor.
Parameters:
re - A real number.
im - An real number representing the imaginary part.
Returns:
A new Complex instance.
*/
var Complex= function() {
if (arguments.length > 1) {
this.x= arguments[0];
this.y= arguments[1];
} else {
this.x= null;
this.y= null;
}
};
Complex.prototype= {
/*
Method: clone
Returns a copy of the current object.
Returns:
A copy of the real object.
*/
clone: function() {
return new Complex(this.x, this.y);
},
/*
Method: toPolar
Transforms cartesian to polar coordinates.
Returns:
A new <Polar> instance.
*/
toPolar: function() {
var rho = this.norm();
var atan = Math.atan2(this.y, this.x);
if(atan < 0) atan += Math.PI * 2;
return new Polar(atan, rho);
},
/*
Method: norm
Calculates the complex norm.
Returns:
A real number representing the complex norm.
*/
norm: function () {
return Math.sqrt(this.squaredNorm());
},
/*
Method: squaredNorm
Calculates the complex squared norm.
Returns:
A real number representing the complex squared norm.
*/
squaredNorm: function () {
return this.x*this.x + this.y*this.y;
},
/*
Method: add
Returns the result of adding two complex numbers.
Does not alter the original object.
Parameters:
pos - A Complex initialized instance.
Returns:
The result of adding two complex numbers.
*/
add: function(pos) {
return new Complex(this.x + pos.x, this.y + pos.y);
},
/*
Method: prod
Returns the result of multiplying two complex numbers.
Does not alter the original object.
Parameters:
pos - A Complex initialized instance.
Returns:
The result of multiplying two complex numbers.
*/
prod: function(pos) {
return new Complex(this.x*pos.x - this.y*pos.y, this.y*pos.x + this.x*pos.y);
},
/*
Method: conjugate
Returns the conjugate por this complex.
Returns:
The conjugate por this complex.
*/
conjugate: function() {
return new Complex(this.x, -this.y);
},
/*
Method: scale
Returns the result of scaling a Complex instance.
Does not alter the original object.
Parameters:
factor - A scale factor.
Returns:
The result of scaling this complex to a factor.
*/
scale: function(factor) {
return new Complex(this.x * factor, this.y * factor);
},
/*
Method: equals
Comparison method.
*/
equals: function(c) {
return this.x == c.x && this.y == c.y;
},
/*
Method: $add
Returns the result of adding two complex numbers.
Alters the original object.
Parameters:
pos - A Complex initialized instance.
Returns:
The result of adding two complex numbers.
*/
$add: function(pos) {
this.x += pos.x; this.y += pos.y;
return this;
},
/*
Method: $prod
Returns the result of multiplying two complex numbers.
Alters the original object.
Parameters:
pos - A Complex initialized instance.
Returns:
The result of multiplying two complex numbers.
*/
$prod:function(pos) {
var x = this.x, y = this.y
this.x = x*pos.x - y*pos.y;
this.y = y*pos.x + x*pos.y;
return this;
},
/*
Method: $conjugate
Returns the conjugate for this complex.
Alters the original object.
Returns:
The conjugate for this complex.
*/
$conjugate: function() {
this.y = -this.y;
return this;
},
/*
Method: $scale
Returns the result of scaling a Complex instance.
Alters the original object.
Parameters:
factor - A scale factor.
Returns:
The result of scaling this complex to a factor.
*/
$scale: function(factor) {
this.x *= factor; this.y *= factor;
return this;
},
/*
Method: $div
Returns the division of two complex numbers.
Alters the original object.
Parameters:
pos - A Complex number.
Returns:
The result of scaling this complex to a factor.
*/
$div: function(pos) {
var x = this.x, y = this.y;
var sq = pos.squaredNorm();
this.x = x * pos.x + y * pos.y; this.y = y * pos.x - x * pos.y;
return this.$scale(1 / sq);
}
};
Complex.KER = new Complex(0, 0);
/*
Class: Polar
A multi purpose polar representation.
*/
/*
Constructor: Polar
Polar constructor.
Parameters:
theta - An angle.
rho - The norm.
Returns:
A new Polar instance.
*/
var Polar = function(theta, rho) {
this.theta = theta;
this.rho = rho;
};
Polar.prototype = {
/*
Method: clone
Returns a copy of the current object.
Returns:
A copy of the real object.
*/
clone: function() {
return new Polar(this.theta, this.rho);
},
/*
Method: toComplex
Translates from polar to cartesian coordinates and returns a new <Complex> instance.
Returns:
A new Complex instance.
*/
toComplex: function() {
return new Complex(Math.cos(this.theta), Math.sin(this.theta)).$scale(this.rho);
},
/*
Method: add
Adds two <Polar> instances.
Returns:
A new Polar instance.
*/
add: function(polar) {
return new Polar(this.theta + polar.theta, this.rho + polar.rho);
},
/*
Method: scale
Scales a polar norm.
Returns:
A new Polar instance.
*/
scale: function(number) {
return new Polar(this.theta, this.rho * number);
},
/*
Method: equals
Comparison method.
*/
equals: function(c) {
return this.theta == c.theta && this.rho == c.rho;
},
/*
Method: $add
Adds two <Polar> instances affecting the current object.
Returns:
The changed object.
*/
$add: function(polar) {
this.theta = this.theta + polar.theta; this.rho += polar.rho;
return this;
},
/*
Method: $madd
Adds two <Polar> instances affecting the current object. The resulting theta angle is modulo 2pi.
Returns:
The changed object.
*/
$madd: function(polar) {
this.theta = (this.theta + polar.theta) % (Math.PI * 2); this.rho += polar.rho;
return this;
},
/*
Method: $scale
Scales a polar instance affecting the object.
Returns:
The changed object.
*/
$scale: function(number) {
this.rho *= number;
return this;
},
/*
Method: interpolate
Calculates a polar interpolation between two points at a given delta moment.
Returns:
A new Polar instance representing an interpolation between _this_ and _elem_
*/
interpolate: function(elem, delta) {
var pi2 = Math.PI * 2;
var ch = function(t) {
return (t < 0)? (t % pi2) + pi2 : t % pi2;
};
var tt = ch(this.theta) , et = ch(elem.theta);
var sum;
if(Math.abs(tt - et) > Math.PI) {
if(tt - et > 0) {
sum =ch((et + ((tt - pi2) - et)* delta)) ;
} else {
sum =ch((et - pi2 + (tt - (et - pi2))* delta));
}
} else {
sum =ch((et + (tt - et)* delta)) ;
}
var t = (sum);
var r = (this.rho - elem.rho) * delta + elem.rho;
return new Polar(t, r);
}
};
Polar.KER = new Polar(0, 0);
/*
Object: Config
<RGraph> global configuration object. Contains important properties to enable customization and proper behavior for the <RGraph>.
*/
var Config= {
//Property: labelContainer
//Id for label container. The label container is a div dom element that must be explicitly added to your page in order to enable the RGraph.
labelContainer: 'label_container',
//Property: drawConcentricCircles
//show/hide concentricCircles
drawConcentricCircles: 4,
//Property: concentricCirclesColor
//The color of the concentric circles
concentricCirclesColor: '#444',
//Property: levelDistance
//The actual distance between levels
levelDistance: 100,
//Property: nodeRadius
//The radius of the nodes displayed
nodeRadius: 4,
//Property: allowVariableNodeDiameters
//Set this to true if you want your node diameters to be proportional to you first dataset object value property (i.e _data[0].value_).
//This will allow you to represent weighted tree/graph nodes.
allowVariableNodeDiameters: false,
//Property: nodeRangeDiameters
//Diameters range. For variable node weights.
nodeRangeDiameters: {
min: 10,
max: 35
},
//Property: nodeRangeValues
// The interval of the values of the first object of your dataSet.
// A superset of the values can also be specified.
nodeRangeValues: {
min: 1,
max: 35
},
//Property: fps
//animation frames per second
fps:40,
//Property: animationTime
animationTime: 2500,
//Property: interpolation
interpolation: 'linear'
};
/*
Object: GraphUtil
A multi purpose object to do graph traversal and processing.
*/
var GraphUtil = {
/*
Method: filter
For internal use only. Provides a filtering function based on flags.
*/
filter: function(param) {
if(!param || !$_.isString(param)) return function() { return true; };
var props = param.split(" ");
return function(elem) {
for(var i=0; i<props.length; i++) if(elem[props[i]]) return false;
return true;
};
},
/*
Method: getNode
Returns a graph's node with a specified _id_.
*/
getNode: function(graph, id) {
return graph.getNode(id);
},
/*
Method: eachNode
Iterates over graph nodes performing an action.
*/
eachNode: function(graph, action, flags) {
var filter = this.filter(flags);
for(var i in graph.nodes) if(filter(graph.nodes[i])) action(graph.nodes[i]);
},
/*
Method: eachAdjacency
Iterates over a _node_ adjacencies applying the _action_ function.
*/
eachAdjacency: function(node, action, flags) {
var adj = node.adjacencies, filter = this.filter(flags);
for(var id in adj) if(filter(adj[id])) action(adj[id], id);
},
/*
Method: computeLevels
Performs a BFS traversal setting correct level for nodes.
*/
computeLevels: function(graph, id, flags) {
var filter = this.filter(flags);
this.eachNode(graph, function(elem) {
elem._flag = false;
elem._depth = -1;
}, flags);
var root = graph.getNode(id);
root._depth = 0;
var queue = [root];
while(queue.length != 0) {
var node = queue.pop();
node._flag = true;
this.eachAdjacency(node, function(adj) {
var n = adj.nodeTo;
if(n._flag == false && filter(n)) {
if(n._depth < 0) n._depth = node._depth + 1;
queue.unshift(n);
}
}, flags);
}
},
/*
Method: eachBFS
Performs a BFS traversal of a graph beginning by the node of id _id_ and performing _action_ on each node.
This traversal ignores nodes or edges having the property _ignore_ setted to _true_.
*/
eachBFS: function(graph, id, action, flags) {
var filter = this.filter(flags);
this.clean(graph);
var queue = [graph.getNode(id)];
while(queue.length != 0) {
var node = queue.pop();
node._flag = true;
action(node, node._depth);
this.eachAdjacency(node, function(adj) {
var n = adj.nodeTo;
if(n._flag == false && filter(n)) {
n._flag = true;
queue.unshift(n);
}
}, flags);
}
},
/*
Method: eachSubnode
After a BFS traversal the _depth_ property of each node has been modified. Now the graph can be traversed as a tree. This method iterates for each subnode that has depth larger than the specified node.
*/
eachSubnode: function(graph, node, action, flags) {
var d = node._depth, filter = this.filter(flags);
this.eachAdjacency(node, function(adj) {
var n = adj.nodeTo;
if(n._depth > d && filter(n)) action(n);
}, flags);
},
/*
Method: getSubnodes
Collects all subnodes for a specified node. The _level_ parameter filters nodes having relative depth of _level_ from the root node.
*/
getSubnodes: function(graph, id, level, flags) {
var ans = new Array(), that = this, node = graph.getNode(id);
(function(graph, node) {
var fn = arguments.callee;
if(!level || level <= node._depth) ans.push(node);
that.eachSubnode(graph, node, function(elem) {
fn(graph, elem);
}, flags);
})(graph, node);
return ans;
},
/*
Method: getParents
Returns all nodes having a depth that is less than the node's depth property.
*/
getParents: function(graph, node) {
var adj = node.adjacencies;
var ans = new Array();
this.eachAdjacency(node, function(adj) {
var n = adj.nodeTo;
if(n._depth < node._depth) ans.push(n);
});
return ans;
},
/*
Method: clean
Cleans flags from nodes (by setting the _flag_ property to false).
*/
clean: function(graph) { this.eachNode(graph, function(elem) { elem._flag = false; }); }
};
/*
Object: GraphOp
An object holding unary and binary graph operations such as removingNodes, removingEdges, adding two graphs and morphing.
*/
var GraphOp = {
options: {
type: 'nothing',
duration: 2000,
fps:30
},
/*
Method: removeNode
Removes one or more nodes from the visualization. It can also perform several animations like fading sequentially, fading concurrently, iterating or replotting.
Parameters:
viz - The visualization object (an RGraph instance in this case).
node - The node's id. Can also be an array having many ids.
opt - Animation options. It's an object with two properties: _type_, which can be _nothing_, _replot_, _fade:seq_, _fade:con_ or _iter_. The other property is the _duration_ in milliseconds.
*/
removeNode: function(viz, node, opt) {
var options = $_.merge(viz.controller, this.options, opt);
var n = $_.isString(node)? [node] : node;
switch(options.type) {
case 'nothing':
for(var i=0; i<n.length; i++) viz.graph.removeNode(n[i]);
break;
case 'replot':
this.removeNode(viz, n, { type: 'nothing' });
GraphPlot.clearLabels(viz);
viz.refresh();
break;
case 'fade:seq': case 'fade':
var GPlot = GraphPlot, that = this;
//set alpha to 0 for nodes to remove.
for(var i=0; i<n.length; i++) {
var nodeObj = viz.graph.getNode(n[i]);
nodeObj.endAlpha = 0;
}
GPlot.animate(viz, $_.merge(options, {
modes: ['fade:nodes'],
onComplete: function() {
that.removeNode(viz, n, { type: 'nothing' });
GPlot.clearLabels(viz);
viz.compute('endPos');
GPlot.animate(viz, $_.merge(options, {
modes: ['linear']
}));
}
}));
break;
case 'fade:con':
var GPlot = GraphPlot, that = this;
//set alpha to 0 for nodes to remove. Tag them for being ignored on computing positions.
for(var i=0; i<n.length; i++) {
var nodeObj = viz.graph.getNode(n[i]);
nodeObj.endAlpha = 0;
nodeObj.ignore = true;
}
viz.compute('endPos');
GPlot.animate(viz, $_.merge(options, {
modes: ['fade:nodes', 'linear'],
onComplete: function() {
that.removeNode(viz, n, { type: 'nothing' });
}
}));
break;
case 'iter':
var that = this, GPlot = GraphPlot;
GPlot.sequence(viz, {
condition: function() { return n.length != 0; },
step: function() { that.removeNode(viz, n.shift(), { type: 'nothing' }); GPlot.clearLabels(viz); },
onComplete: function() { options.onComplete(); },
duration: Math.ceil(options.duration / n.length)
});
break;
default: this.doError();
}
},
/*
Method: removeEdge
Removes one or more edges from the visualization. It can also perform several animations like fading sequentially, fading concurrently, iterating or replotting.
Parameters:
viz - The visualization object (an RGraph instance in this case).
vertex - An array having two strings which are the ids of the nodes connected by this edge: ['id1', 'id2']. Can also be a two dimensional array holding many edges: [['id1', 'id2'], ['id3', 'id4'], ...].
opt - Animation options. It's an object with two properties: _type_, which can be _nothing_, _replot_, _fade:seq_, _fade:con_ or _iter_. The other property is the _duration_ in milliseconds.
*/
removeEdge: function(viz, vertex, opt) {
var options = $_.merge(viz.controller, this.options, opt);
var v = $_.isString(vertex[0])? [vertex] : vertex;
switch(options.type) {
case 'nothing':
for(var i=0; i<v.length; i++) viz.graph.removeAdjacence(v[i][0], v[i][1]);
break;
case 'replot':
this.removeEdge(viz, v, { type: 'nothing' });
viz.refresh();
break;
case 'fade:seq': case 'fade':
var GPlot = GraphPlot, that = this;
//set alpha to 0 for nodes to remove.
for(var i=0; i<v.length; i++) {
var adjs = viz.graph.getAdjacence(v[i][0], v[i][1]);
if(adjs) {
adjs[0].endAlpha = 0;
adjs[1].endAlpha = 0;
}
}
GPlot.animate(viz, $_.merge(options, {
modes: ['fade:vertex'],
onComplete: function() {
that.removeEdge(viz, v, { type: 'nothing' });
viz.compute('endPos');
GPlot.animate(viz, $_.merge(options, {
modes: ['linear']
}));
}
}));
break;
case 'fade:con':
var GPlot = GraphPlot, that = this;
//set alpha to 0 for nodes to remove. Tag them for being ignored when computing positions.
for(var i=0; i<v.length; i++) {
var adjs = viz.graph.getAdjacence(v[i][0], v[i][1]);
if(adjs) {
adjs[0].endAlpha = 0;
adjs[0].ignore = true;
adjs[1].endAlpha = 0;
adjs[1].ignore = true;
}
}
viz.compute('endPos');
GPlot.animate(viz, $_.merge(options, {
modes: ['fade:vertex', 'linear'],
onComplete: function() {
that.removeEdge(viz, v, { type: 'nothing' });
}
}));
break;
case 'iter':
var that = this, GPlot = GraphPlot;
GPlot.sequence(viz, {
condition: function() { return v.length != 0; },
step: function() { that.removeEdge(viz, v.shift(), { type: 'nothing' }); GPlot.clearLabels(viz); },
onComplete: function() { options.onComplete(); },
duration: Math.ceil(options.duration / v.length)
});
break;
default: this.doError();
}
},
/*
Method: sum
Adds a new graph to the visualization. The json graph (or tree) must at least have a common node with the current graph plotted by the visualization. The resulting graph can be defined as follows: <http://mathworld.wolfram.com/GraphSum.html>
Parameters:
viz - The visualization object (an RGraph instance in this case).
json - A json tree <http://blog.thejit.org/2008/04/27/feeding-json-tree-structures-to-the-jit/>, a json graph <http://blog.thejit.org/2008/07/02/feeding-json-graph-structures-to-the-jit/> or an extended json graph <http://blog.thejit.org/2008/08/05/weighted-nodes-weighted-edges/>.
opt - Animation options. It's an object with two properties: _type_, which can be _nothing_, _replot_, _fade:seq_, or _fade:con_. The other property is the _duration_ in milliseconds.
*/
sum: function(viz, json, opt) {
var options = $_.merge(viz.controller, this.options, opt), root = viz.root;
viz.root = opt.id || viz.root;
switch(options.type) {
case 'nothing':
var graph = viz.construct(json), GUtil = GraphUtil;
GUtil.eachNode(graph, function(elem) {
GUtil.eachAdjacency(elem, function(adj) {
viz.graph.addAdjacence(adj.nodeFrom, adj.nodeTo, adj.data);
});
});
break;
case 'replot':
this.sum(viz, json, { type: 'nothing' });
viz.refresh();
break;
case 'fade:seq': case 'fade': case 'fade:con':
var GUtil = GraphUtil, GPlot = GraphPlot, that = this, graph = viz.construct(json);
//set alpha to 0 for nodes to add.
var fadeEdges = this.preprocessSum(viz, graph);
var modes = !fadeEdges? ['fade:nodes'] : ['fade:nodes', 'fade:vertex'];
viz.compute('endPos');
if(options.type != 'fade:con') {
GPlot.animate(viz, $_.merge(options, {
modes: ['linear'],
onComplete: function() {
GPlot.animate(viz, $_.merge(options, {
modes: modes,
onComplete: function() {
options.onComplete();
}
}));
}
}));
} else {
GUtil.eachNode(viz.graph, function(elem) {
if(elem.id != root && elem.pos.equals(Polar.KER)) elem.pos = elem.startPos = elem.endPos;
});
GPlot.animate(viz, $_.merge(options, {
modes: ['linear'].concat(modes),
onComplete: function() {
options.onComplete();
}
}));
}
break;
default: this.doError();
}
},
/*
Method: morph
This method will _morph_ the current visualized graph into the new _json_ representation passed in the method. Can also perform multiple animations. The _json_ object must at least have the root node in common with the current visualized graph.
Parameters:
viz - The visualization object (an RGraph instance in this case).
json - A json tree <http://blog.thejit.org/2008/04/27/feeding-json-tree-structures-to-the-jit/>, a json graph <http://blog.thejit.org/2008/07/02/feeding-json-graph-structures-to-the-jit/> or an extended json graph <http://blog.thejit.org/2008/08/05/weighted-nodes-weighted-edges/>.
opt - Animation options. It's an object with two properties: _type_, which can be _nothing_, _replot_, or _fade_. The other property is the _duration_ in milliseconds.
*/
morph: function(viz, json, opt) {
var options = $_.merge(viz.controller, this.options, opt), root = viz.root;
viz.root = opt.id || viz.root;
switch(options.type) {
case 'nothing':
var graph = viz.construct(json), GUtil = GraphUtil;
GUtil.eachNode(graph, function(elem) {
GUtil.eachAdjacency(elem, function(adj) {
viz.graph.addAdjacence(adj.nodeFrom, adj.nodeTo, adj.data);
});
});
GUtil.eachNode(viz.graph, function(elem) {
GUtil.eachAdjacency(elem, function(adj) {
if(!graph.getAdjacence(adj.nodeFrom.id, adj.nodeTo.id)) {
viz.graph.removeAdjacence(adj.nodeFrom.id, adj.nodeTo.id);
}
if(!viz.graph.hasNode(elem.id)) viz.graph.removeNode(elem.id);
});
});
break;
case 'replot':
this.morph(viz, json, { type: 'nothing' });
viz.refresh();
break;
case 'fade:seq': case 'fade': case 'fade:con':
var GUtil = GraphUtil, GPlot = GraphPlot, that = this, graph = viz.construct(json);
//preprocessing for adding nodes.
var fadeEdges = this.preprocessSum(viz, graph);
//preprocessing for nodes to delete.
GUtil.eachNode(viz.graph, function(elem) {
if(!graph.hasNode(elem.id)) {
elem.alpha = 1; elem.startAlpha = 1; elem.endAlpha = 0; elem.ignore = true;
}
});
GUtil.eachNode(viz.graph, function(elem) {
if(elem.ignore) return;
GUtil.eachAdjacency(elem, function(adj) {
if(adj.nodeFrom.ignore || adj.nodeTo.ignore) return;
var nodeFrom = graph.getNode(adj.nodeFrom.id);
var nodeTo = graph.getNode(adj.nodeTo.id);
if(!nodeFrom.adjacentTo(nodeTo)) {
var adjs = viz.graph.getAdjacence(nodeFrom.id, nodeTo.id);
fadeEdges = true;
adjs[0].alpha = 1; adjs[0].startAlpha = 1; adjs[0].endAlpha = 0; adjs[0].ignore = true;
adjs[1].alpha = 1; adjs[1].startAlpha = 1; adjs[1].endAlpha = 0; adjs[1].ignore = true;
}
});
});
var modes = !fadeEdges? ['fade:nodes'] : ['fade:nodes', 'fade:vertex'];
viz.compute('endPos');
GUtil.eachNode(viz.graph, function(elem) {
if(elem.id != root && elem.pos.equals(Polar.KER)) elem.pos = elem.startPos = elem.endPos;
});
GPlot.animate(viz, $_.merge(options, {
modes: ['polar'].concat(modes),
onComplete: function() {
GUtil.eachNode(viz.graph, function(elem) {
if(elem.ignore) viz.graph.removeNode(elem.id);
});
GUtil.eachNode(viz.graph, function(elem) {
GUtil.eachAdjacency(elem, function(adj) {
if(adj.ignore) viz.graph.removeAdjacence(adj.nodeFrom.id, adj.nodeTo.id);
});
});
options.onComplete();
}
}));
break;
default: this.doError();
}
},
preprocessSum: function(viz, graph) {
var GUtil = GraphUtil;
GUtil.eachNode(graph, function(elem) {
if(!viz.graph.hasNode(elem.id)) {
viz.graph.addNode(elem);
var n = viz.graph.getNode(elem.id);
n.alpha = 0; n.startAlpha = 0; n.endAlpha = 1;
}
});
var fadeEdges = false;
GUtil.eachNode(graph, function(elem) {
GUtil.eachAdjacency(elem, function(adj) {
var nodeFrom = viz.graph.getNode(adj.nodeFrom.id);
var nodeTo = viz.graph.getNode(adj.nodeTo.id);
if(!nodeFrom.adjacentTo(nodeTo)) {
var adjs = viz.graph.addAdjacence(nodeFrom, nodeTo, adj.data);
if(nodeFrom.startAlpha == nodeFrom.endAlpha
&& nodeTo.startAlpha == nodeTo.endAlpha) {
fadeEdges = true;
adjs[0].alpha = 0; adjs[0].startAlpha = 0; adjs[0].endAlpha = 1;
adjs[1].alpha = 0; adjs[1].startAlpha = 0; adjs[1].endAlpha = 1;
}
}
});
});
return fadeEdges;
}
};
/*
Object: GraphPlot
An object that performs specific radial layouts for a generic graph structure.
*/
var GraphPlot = {
Interpolator: {
'polar': function(elem, delta) {
var from = elem.startPos;
var to = elem.endPos;
elem.pos = to.interpolate(from, delta);
},
'linear': function(elem, delta) {
var from = elem.startPos.toComplex();
var to = elem.endPos.toComplex();
elem.pos = ((to.$add(from.scale(-1))).$scale(delta).$add(from)).toPolar();
},
'fade:nodes': function(elem, delta) {
if(elem.endAlpha != elem.alpha) {
var from = elem.startAlpha;
var to = elem.endAlpha;
elem.alpha = from + (to - from) * delta;
}
},
'fade:vertex': function(elem, delta) {
var adjs = elem.adjacencies;
for(var id in adjs) this['fade:nodes'](adjs[id], delta);
}
},
//Property: labelsHidden
//A flag value indicating if node labels are being displayed or not.
labelsHidden: false,
//Property: labelContainer
//Label DOM element
labelContainer: false,
//Property: labels
//Label DOM elements hash.
labels: {},
/*
Method: getLabelContainer
Lazy fetcher for the label container.
*/
getLabelContainer: function() {
return this.labelContainer? this.labelContainer : this.labelContainer = document.getElementById(Config.labelContainer);
},
/*
Method: getLabel
Lazy fetcher for the label DOM element.
*/
getLabel: function(id) {
return (id in this.labels && this.labels[id] != null)? this.labels[id] : this.labels[id] = document.getElementById(id);
},
/*
Method: hideLabels
Hides all labels.
*/
hideLabels: function (hide) {
var container = this.getLabelContainer();
if(hide) container.style.display = 'none';
else container.style.display = '';
this.labelsHidden = hide;
},
/*
Method: clearLabels
Clears the label container.
*/
clearLabels: function(viz) {
for(var id in this.labels)
if(!viz.graph.hasNode(id)) {
this.disposeLabel(id);
delete this.labels[id];
}
},
/*
Method: disposeLabel
Removes a label.
*/
disposeLabel: function(id) {
var elem = this.getLabel(id);
if(elem && elem.parentNode) {
elem.parentNode.removeChild(elem);
}
},
/*
Method: animate
Animates the graph mantaining a radial layout.
*/
animate: function(viz, opt) {
var that = this, GUtil = GraphUtil, Anim = Animation, duration = opt.duration || Anim.duration, fps = opt.fps || Anim.fps;
//Should be changed eventually, when Animation becomes a class.
var prevDuration = Anim.duration, prevFps = Anim.fps;
Anim.duration = duration;
Anim.fps = fps;
if(opt.hideLabels) this.hideLabels(true);
var animationController = {
compute: function(delta) {
GUtil.eachNode(viz.graph, function(node) {
for(var i=0; i<opt.modes.length; i++) {
that.Interpolator[opt.modes[i]](node, delta);
}
});
that.plot(viz, opt);
},
complete: function() {
GUtil.eachNode(viz.graph, function(node) {
node.startPos = node.pos;
node.startAlpha = node.alpha;
});
if(opt.hideLabels) that.hideLabels(false);
that.plot(viz, opt);
Anim.duration = prevDuration;
Anim.fps = prevFps;
opt.onComplete();
opt.onAfterCompute();
}
};
Anim.controller = animationController;
Anim.start();
},
/*
Method: sequence
Iteratively performs an action while refreshing the state of the visualization.
*/
sequence: function(viz, options) {
options = $_.merge({
condition: function() { return false; },
step: $_.fn(),
onComplete: $_.fn(),
duration: 200
}, options);
var interval = setInterval(function() {
if(options.condition()) {
options.step();
} else {
clearInterval(interval);
options.onComplete();
}
viz.refresh();
}, options.duration);
},
/*
Method: plot
Plots a Graph.
*/
plot: function(viz, opt) {
var aGraph = viz.graph, canvas = viz.canvas, id = viz.root;
var that = this, ctx = canvas.getContext(), GUtil = GraphUtil;
canvas.clear();
if(Config.drawConcentricCircles) canvas.drawConcentricCircles(Config.drawConcentricCircles);
var T = !!aGraph.getNode(id).visited;
GUtil.eachNode(aGraph, function(node) {
GUtil.eachAdjacency(node, function(adj) {
if(!!adj.nodeTo.visited === T) {
opt.onBeforePlotLine(adj);
ctx.save();
ctx.globalAlpha = Math.min(Math.min(node.alpha, adj.nodeTo.alpha), adj.alpha);
that.plotLine(adj, canvas);
ctx.restore();
opt.onAfterPlotLine(adj);
}
});
ctx.save();
ctx.globalAlpha = node.alpha;
that.plotNode(node, canvas);
if(!that.labelsHidden && ctx.globalAlpha >= .95) that.plotLabel(canvas, node, opt);
else if(!that.labelsHidden && ctx.globalAlpha < .95) that.hideLabel(node);
ctx.restore();
node.visited = !T;
});
},
/*
Method: plotNode
Plots a graph node.
*/
plotNode: function(node, canvas) {
var pos = node.pos.toComplex();
canvas.path('fill', function(context) {
context.arc(pos.x, pos.y, node._radius, 0, Math.PI*2, true);
});
},
/*
Method: plotLine
Plots a line connecting _node_ and _child_ nodes.
*/
plotLine: function(adj, canvas) {
var node = adj.nodeFrom, child = adj.nodeTo;
var pos = node.pos.toComplex();
var posChild = child.pos.toComplex();
canvas.path('stroke', function(context) {
context.moveTo(pos.x, pos.y);
context.lineTo(posChild.x, posChild.y);
});
},
/*
Method: hideLabel
Hides a label having _node.id_ as id.
*/
hideLabel: function(node) {
var n; if(n = document.getElementById(node.id)) n.style.display = "none";
},
/*
Method: plotLabel
Plots a label for a given node.
*/
plotLabel: function(canvas, node, controller) {
var size = node._radius, id = node.id, tag = this.getLabel(id);
if(!tag && !(tag = document.getElementById(id))) {
tag = document.createElement('div');
var container = this.getLabelContainer();
container.appendChild(tag);
tag.id = id;
tag.className = 'node';
tag.style.position = 'absolute';
controller.onCreateLabel(tag, node);
}
var pos = node.pos.toComplex();
var radius= canvas.getSize();
var cpos = canvas.getPosition();
var labelPos= {
x: Math.round(pos.x + cpos.x + radius.x/2 - size /2),
y: Math.round(pos.y + cpos.y + radius.y/2 - size /2)
};
if(tag.style && size){
tag.style.width = size + 'px';
tag.style.height = size + 'px';
tag.style.left = labelPos.x + 'px';
tag.style.top = labelPos.y + 'px';
tag.style.display = this.fitsInCanvas(labelPos, canvas)? '' : 'none';
}
controller.onPlaceLabel(tag, node);
},
/*
Method: fitsInCanvas
Returns _true_ or _false_ if the label for the node is contained on the canvas dom element or not.
*/
fitsInCanvas: function(pos, canvas) {
var size = canvas.getSize();
if(pos.x >= size.x + canvas.position.x || pos.x < canvas.position.x
|| pos.y >= size.y + canvas.position.y || pos.y < canvas.position.y) return false;
return true;
}
};
/*
Class: RGraph
An animated Graph with radial layout.
Go to <http://blog.thejit.org> to know what kind of JSON structure feeds this object.
Go to <http://blog.thejit.org/?p=8> to know what kind of controller this class accepts.
Refer to the <Config> object to know what properties can be modified in order to customize this object.
The simplest way to create and layout a RGraph is:
(start code)
var canvas= new Canvas('infovis', '#ccddee', '#772277');
var rgraph= new RGraph(canvas, controller);
rgraph.loadTreeFromJSON(json);
rgraph.compute();
rgraph.plot();
(end code)
A user should only interact with the Canvas, RGraph and Config objects/classes.
By implementing RGraph controllers you can also customize the RGraph behavior.
*/
/*
Constructor: RGraph
Creates a new RGraph instance.
Parameters:
canvas - A <Canvas> instance.
controller - _optional_ a RGraph controller <http://blog.thejit.org/?p=8>
*/
var RGraph = function(canvas, controller) {
var innerController = {
onBeforeCompute: $_.fn(),
onAfterCompute: $_.fn(),
onCreateLabel: $_.fn(),
onPlaceLabel: $_.fn(),
onCreateElement: $_.fn(),
onComplete: $_.fn(),
onBeforePlotLine: $_.fn(),
onAfterPlotLine: $_.fn(),
request: false
};
this.controller = $_.merge(innerController, controller);
this.graph = new Graph();
this.json = null;
this.canvas = canvas;
this.root = null;
this.busy = false;
Animation.duration = Config.animationTime;
Animation.fps = Config.fps;
};
RGraph.prototype = {
construct: function(json) {
var isGraph = $_.isArray(json);
var ans = new Graph();
if(!isGraph)
//make tree
(function (ans, json) {
ans.addNode(json);
for(var i=0, ch = json.children; i<ch.length; i++) {
ans.addAdjacence(json, ch[i]);
arguments.callee(ans, ch[i]);
}
})(ans, json);
else
//make graph
(function (ans, json) {
var getNode = function(id) {
for(var w=0; w<json.length; w++) if(json[w].id == id) return json[w];
};
for(var i=0; i<json.length; i++) {
ans.addNode(json[i]);
for(var j=0, adj = json[i].adjacencies; j<adj.length; j++) {
var node = adj[j], data;
if(typeof adj[j] != 'string') {
data = node.data;
node = node.nodeTo;
}
ans.addAdjacence(json[i], getNode(node), data);
}
}
})(ans, json);
return ans;
},
/*
Method: loadTree
Loads a Graph from a json tree object <http://blog.thejit.org>
*/
loadTree: function(json) {
this.graph = this.construct(json);
},
/*
Method: loadGraph
Loads a Graph from a json graph object <http://blog.thejit.org>
*/
loadGraph: function(json) {
this.graph = this.construct(json);
},
/*
Method: refresh
Computes positions and then plots.
*/
refresh: function() {
this.compute();
this.plot();
},
/*
Method: flagRoot
Flags a node specified by _id_ as root.
*/
flagRoot: function(id) {
this.unflagRoot();
this.graph.nodes[id]._root = true;
},
/*
Method: unflagRoot
Unflags all nodes.
*/
unflagRoot: function() {
GraphUtil.eachNode(this.graph, function(elem) {elem._root = false;});
},
/*
Method: getRoot
Returns the node flagged as root.
*/
getRoot: function() {
var root = false;
GraphUtil.eachNode(this.graph, function(elem){ if(elem._root) root = elem; });
return root;
},
/*
Method: loadTreeFromJSON
Loads a RGraph from a _json_ object <http://blog.thejit.org>
*/
loadTreeFromJSON: function(json) {
this.json = json;
this.loadTree(json);
this.root = json.id;
},
/*
Method: loadGraphFromJSON
Loads a RGraph from a _json_ object <http://blog.thejit.org>
*/
loadGraphFromJSON: function(json, i) {
this.json = json;
this.loadGraph(json);
this.root = json[i? i : 0].id;
},
/*
Method: plot
Plots the RGraph
*/
plot: function() {
GraphPlot.plot(this, this.controller);
},
/*
Method: compute
Computes the graph nodes positions and stores this positions on _property_.
*/
compute: function(property) {
var prop = property || ['pos', 'startPos', 'endPos'];
var node = this.graph.getNode(this.root);
node._depth = 0;
this.flagRoot(this.root);
GraphUtil.computeLevels(this.graph, this.root, "ignore");
this.computeAngularWidths();
this.computePositions(prop);
},
/*
Method: computePositions
Performs the main algorithm for computing node positions.
*/
computePositions: function(property) {
var propArray = (typeof property == 'array' || typeof property == 'object')? property : [property];
var aGraph = this.graph;
var GUtil = GraphUtil;
var root = this.graph.getNode(this.root);
for(var i=0; i<propArray.length; i++)
root[propArray[i]] = new Polar(0, 0);
root.angleSpan = {
begin: 0,
end: 2 * Math.PI
};
root._rel = 1;
GUtil.eachBFS(this.graph, this.root, function (elem) {
var angleSpan = elem.angleSpan.end - elem.angleSpan.begin;
var rho = (elem._depth + 1) * Config.levelDistance;
var angleInit = elem.angleSpan.begin;
var totalAngularWidths = (function (element){
var total = 0;
GUtil.eachSubnode(aGraph, element, function(sib) {
total += sib._treeAngularWidth;
}, "ignore");
return total;
})(elem);
GUtil.eachSubnode(aGraph, elem, function(child) {
if(!child._flag) {
child._rel = child._treeAngularWidth / totalAngularWidths;
var angleProportion = child._rel * angleSpan;
var theta = angleInit + angleProportion / 2;
for(var i=0; i<propArray.length; i++)
child[propArray[i]] = new Polar(theta, rho);
child.angleSpan = {
begin: angleInit,
end: angleInit + angleProportion
};
angleInit += angleProportion;
}
}, "ignore");
}, "ignore");
},
/*
Method: setAngularWidthForNodes
Sets nodes angular widths.
*/
setAngularWidthForNodes: function() {
var rVal = Config.nodeRangeValues, rDiam = Config.nodeRangeDiameters, nr = Config.nodeRadius, allow = Config.allowVariableNodeDiameters;
var diam = function(value) { return (((rDiam.max - rDiam.min)/(rVal.max - rVal.min)) * (value - rVal.min) + rDiam.min) };
GraphUtil.eachBFS(this.graph, this.root, function(elem, i) {
var dataValue = (allow && elem.data && elem.data.length > 0)? elem.data[0].value : nr;
var diamValue = diam(dataValue);
var rho = Config.levelDistance * i;
elem._angularWidth = diamValue / rho;
elem._radius = allow? diamValue / 2 : nr;
}, "ignore");
},
/*
Method: setSubtreesAngularWidths
Sets subtrees angular widths.
*/
setSubtreesAngularWidth: function() {
var that = this;
GraphUtil.eachNode(this.graph, function(elem) {
that.setSubtreeAngularWidth(elem);
}, "ignore");
},
/*
Method: setSubtreeAngularWidth
Sets the angular width for a subtree.
*/
setSubtreeAngularWidth: function(elem) {
var that = this, nodeAW = elem._angularWidth, sumAW = 0;
GraphUtil.eachSubnode(this.graph, elem, function(child) {
that.setSubtreeAngularWidth(child);
sumAW += child._treeAngularWidth;
}, "ignore");
elem._treeAngularWidth = Math.max(nodeAW, sumAW);
},
/*
Method: computeAngularWidths
Computes nodes and subtrees angular widths.
*/
computeAngularWidths: function () {
this.setAngularWidthForNodes();
this.setSubtreesAngularWidth();
},
/*
Method: getNodeAndParentAngle
Returns the _parent_ of the given node, also calculating its angle span.
*/
getNodeAndParentAngle: function(id) {
var theta = false;
var n = this.graph.getNode(id);
var ps = GraphUtil.getParents(this.graph, n);
var p = (ps.length > 0)? ps[0] : false;
if(p) {
var posParent = p.pos.toComplex(), posChild = n.pos.toComplex();
var newPos = posParent.add(posChild.scale(-1));
theta = (function(pos) {
var t = Math.atan2(pos.y, pos.x);
if(t < 0) t = 2 * Math.PI + t;
return t;
})(newPos);
}
return {_parent: p, theta: theta};
},
/*
Method: onClick
Performs all calculations and animation when clicking on a label specified by _id_. The label id is the same id as its homologue node.
*/
onClick: function(id) {
if(this.root != id && !this.busy) {
this.busy = true;
//we apply first constraint to the algorithm
var obj = this.getNodeAndParentAngle(id);
this.root = id, that = this;
this.controller.onBeforeCompute(this.graph.getNode(id));
var thetaDiff = obj.theta - obj._parent.endPos.theta;
GraphUtil.eachNode(this.graph, function(elem) {
elem.endPos = elem.endPos.add(new Polar(thetaDiff, 0));
});
var mode = (Config.interpolation == 'linear')? 'linear' : 'polar';
GraphPlot.animate(this, $_.merge(this.controller, {
hideLabels:true,
modes: [mode],
onComplete: function() {
that.busy = false;
}
}));
}
}
};
/*
Class: Graph
A generic Graph class.
*/
/*
Constructor: Graph
Creates a new Graph instance.
*/
var Graph= function() {
//Property: nodes
//graph nodes
this.nodes= {};
};
Graph.prototype= {
/*
Method: getNode
Returns a <Graph.Node> from a specified _id_.
*/
getNode: function(id) {
if(this.hasNode(id)) return this.nodes[id];
return false;
},
/*
Method: getAdjacence
Returns an array of <Graph.Adjacence> that connects nodes with id _id_ and _id2_.
*/
getAdjacence: function (id, id2) {
var adjs = [];
if(this.hasNode(id) && this.hasNode(id2)
&& this.nodes[id].adjacentTo({ 'id':id2 }) && this.nodes[id2].adjacentTo({ 'id':id })) {
adjs.push(this.nodes[id].getAdjacency(id2));
adjs.push(this.nodes[id2].getAdjacency(id));
return adjs;
}
return false;
},
/*
Method: addNode
Adds a node.
Parameters:
obj - A <Graph.Node> object.
*/
addNode: function(obj) {
if(!this.nodes[obj.id]) {
this.nodes[obj.id] = new Graph.Node(obj.id, obj.name, obj.data);
}
return this.nodes[obj.id];
},
/*
Method: addAdjacence
Connects nodes specified by *obj* and *obj2*. If not found, nodes are created.
Parameters:
obj - a <Graph.Node> object.
obj2 - Another <Graph.Node> object.
data - A DataSet object.
*/
addAdjacence: function (obj, obj2, weight) {
var adjs = []
if(!this.hasNode(obj.id)) this.addNode(obj);
if(!this.hasNode(obj2.id)) this.addNode(obj2);
obj = this.nodes[obj.id]; obj2 = this.nodes[obj2.id];
for(var i in this.nodes) {
if(this.nodes[i].id == obj.id) {
if(!this.nodes[i].adjacentTo(obj2)) {
adjs.push(this.nodes[i].addAdjacency(obj2, weight));
}
}
if(this.nodes[i].id == obj2.id) {
if(!this.nodes[i].adjacentTo(obj)) {
adjs.push(this.nodes[i].addAdjacency(obj, weight));
}
}
}
return adjs;
},
/*
Method: removeNode
Removes a <Graph.Node> from <Graph> that matches the specified _id_.
*/
removeNode: function(id) {
if(this.hasNode(id)) {
var node = this.nodes[id];
for(var i=0 in node.adjacencies) {
var adj = node.adjacencies[i];
this.removeAdjacence(id, adj.nodeTo.id);
}
delete this.nodes[id];
}
},
/*
Method: removeAdjacence
Removes a <Graph.Adjacence> from <Graph> that matches the specified _id1_ and _id2_.
*/
removeAdjacence: function(id1, id2) {
if(this.hasNode(id1)) this.nodes[id1].removeAdjacency(id2);
if(this.hasNode(id2)) this.nodes[id2].removeAdjacency(id1);
},
/*
Method: hasNode
Returns a Boolean instance indicating if node belongs to graph or not.
Parameters:
id - Node id.
Returns:
A Boolean instance indicating if node belongs to graph or not.
*/
hasNode: function(id) {
return id in this.nodes;
}
};
/*
Class: Graph.Node
Behaviour of the <Graph> node.
*/
/*
Constructor: Graph.Node
Node constructor.
Parameters:
id - The node *unique identifier* id.
name - A node's name.
data - Place to store some extra information (can be left to null).
Returns:
A new <Graph.Node> instance.
*/
Graph.Node = function(id, name, data) {
//Property: id
//A node's id
this.id= id;
//Property: name
//A node's name
this.name = name;
//Property: data
//The dataSet object <http://blog.thejit.org/?p=7>
this.data = data;
//Property: drawn
//Node flag
this.drawn= false;
//Property: angle span
//allowed angle span for adjacencies placement
this.angleSpan= {
begin:0,
end:0
};
//Property: pos
//node position
this.pos= new Polar(0, 0);
//Property: startPos
//node from position
this.startPos= new Polar(0, 0);
//Property: endPos
//node to position
this.endPos= new Polar(0, 0);
//Property: alpha
//node alpha
this.alpha = 1;
//Property: startAlpha
//node start alpha
this.startAlpha = 1;
//Property: endAlpha
//node end alpha
this.endAlpha = 1;
//Property: adjacencies
//node adjacencies
this.adjacencies= {};
};
Graph.Node.prototype= {
/*
Method: adjacentTo
Indicates if the node is adjacent to the node indicated by the specified id
Parameters:
id - A node id.
Returns:
A Boolean instance indicating whether this node is adjacent to the specified by id or not.
*/
adjacentTo: function(node) {
return node.id in this.adjacencies;
},
/*
Method: getAdjacency
Returns a <Graph.Adjacence> that connects the current <Graph.Node> with the node having _id_ as id.
Parameters:
id - A node id.
*/
getAdjacency: function(id) {
return this.adjacencies[id];
},
/*
Method: addAdjacency
Connects the node to the specified by id.
Parameters:
id - A node id.
*/
addAdjacency: function(node, data) {
var adj = new Graph.Adjacence(this, node, data);
return this.adjacencies[node.id] = adj;
},
/*
Method: removeAdjacency
Deletes the <Graph.Adjacence> by _id_.
Parameters:
id - A node id.
*/
removeAdjacency: function(id) {
delete this.adjacencies[id];
}
};
/*
Class: Graph.Adjacence
Creates a new <Graph> adjacence.
*/
Graph.Adjacence = function(nodeFrom, nodeTo, data) {
//Property: nodeFrom
//One of the two <Graph.Node>s connected by this edge.
this.nodeFrom = nodeFrom;
//Property: nodeTo
//One of the two <Graph.Node>s connected by this edge.
this.nodeTo = nodeTo;
//Property: data
//A dataset object
this.data = data;
//Property: alpha
//node alpha
this.alpha = 1;
//Property: startAlpha
//node start alpha
this.startAlpha = 1;
//Property: endAlpha
//node end alpha
this.endAlpha = 1;
};
/*
Object: Trans
An object containing multiple type of transformations. Based on the mootools library <http://mootools.net>.
*/
var Trans = {
linear: function(p) { return p; },
Quart: function(p) {
return Math.pow(p, 4);
},
easeIn: function(transition, pos){
return transition(pos);
},
easeOut: function(transition, pos){
return 1 - transition(1 - pos);
},
easeInOut: function(transition, pos){
return (pos <= 0.5) ? transition(2 * pos) / 2 : (2 - transition(2 * (1 - pos))) / 2;
}
};
/*
Object: Animation
An object that performs animations. Based on Fx.Base from Mootools.
*/
var Animation = {
duration: Config.animationTime,
fps: Config.fps,
transition: function(p) {return Trans.easeInOut(Trans.Quart, p);},
//transition: Trans.linear,
controller: false,
getTime: function() {
var ans = (Date.now)? Date.now() : new Date().getTime();
return ans;
},
step: function(){
var time = this.getTime();
if (time < this.time + this.duration){
var delta = this.transition((time - this.time) / this.duration);
this.controller.compute(delta);
} else {
this.timer = clearInterval(this.timer);
this.controller.compute(1);
this.controller.complete();
}
},
start: function(){
this.time = 0;
this.startTimer();
return this;
},
startTimer: function(){
if (this.timer) return false;
this.time = this.getTime() - this.time;
this.timer = setInterval((function () { Animation.step(); }), Math.round(1000 / this.fps));
return true;
}
};
/*Jon's JIT Hacks */
Config.animationTime = 1000;
/*RGRAPH*/
RGraph.prototype.offsetCenter= function(x,y){
var d =this.controller.getOffset();
d.x = x;
d.y = y;
this.controller.setOffset(d);
};
RGraph.prototype.setAngularWidthForNodes= function() {
var rVal = Config.nodeRangeValues, rDiam = Config.nodeRangeDiameters, nr = Config.nodeRadius, allow = Config.allowVariableNodeDiameters;
var zoom = this.controller.getZoomLevel();
var diam = function(value) { return (((rDiam.max - rDiam.min)/(rVal.max - rVal.min)) * (value - rVal.min) + rDiam.min) };
GraphUtil.eachBFS(this.graph, this.root, function(elem, i) {
var dataValue = (allow && elem.data && elem.data.length > 0)? elem.data[0].value : nr;
var diamValue = diam(dataValue);
var rho = zoom * i;//jon
elem._angularWidth = diamValue / rho;
elem._radius = allow? diamValue / 2 : nr;
}, "ignore");
};
RGraph.prototype.computePositions= function(property) {
var propArray = (typeof property == 'array' || typeof property == 'object')? property : [property];
var aGraph = this.graph;
var GUtil = GraphUtil;
var root = this.graph.getNode(this.root);
for(var i=0; i<propArray.length; i++)
root[propArray[i]] = new Polar(0, 0);
root.angleSpan = {
begin: 0,
end: 2 * Math.PI
};
root._rel = 1;
var zoom =this.controller.getZoomLevel();
GUtil.eachBFS(this.graph, this.root, function (elem) {
var angleSpan = elem.angleSpan.end - elem.angleSpan.begin;
var rho = (elem._depth + 1) * zoom;//jon
var angleInit = elem.angleSpan.begin;
var totalAngularWidths = (function (element){
var total = 0;
GUtil.eachSubnode(aGraph, element, function(sib) {
total += sib._treeAngularWidth;
}, "ignore");
return total;
})(elem);
GUtil.eachSubnode(aGraph, elem, function(child) {
if(!child._flag) {
child._rel = child._treeAngularWidth / totalAngularWidths;
var angleProportion = child._rel * angleSpan;
var theta = angleInit + angleProportion / 2;
for(var i=0; i<propArray.length; i++)
child[propArray[i]] = new Polar(theta, rho);
child.angleSpan = {
begin: angleInit,
end: angleInit + angleProportion
};
angleInit += angleProportion;
}
}, "ignore");
}, "ignore");
};
RGraph.prototype.onClick= function(id) { //weird bug in here
if(this.root != id) {//jon
this.busy = true;
//we apply first constraint to the algorithm
var obj = this.getNodeAndParentAngle(id);
this.root = id, that = this;
this.controller.onBeforeCompute(this.graph.getNode(id));
this.compute('endPos');
var thetaDiff = obj.theta - obj._parent.endPos.theta;
GraphUtil.eachNode(this.graph, function(elem) {
elem.endPos = elem.endPos.add(new Polar(thetaDiff, 0));
});
var mode = (Config.interpolation == 'linear')? 'linear' : 'polar';
this.controller.modes = [mode];//jon
GraphPlot.animate(this, this.controller);//jon
}
};
/*GRAPH PLOT */
GraphPlot.plotLine = function(adj, canvas,controller) {//jon
var d = controller.getOffset();//jon
var node = adj.nodeFrom, child = adj.nodeTo;
var pos = node.pos.toComplex();
var posChild = child.pos.toComplex();
canvas.path('stroke', function(context) {
pos.x += d.x;//jon..
pos.y += d.y;
posChild.x += d.x;
posChild.y += d.y;//..jon
context.moveTo(pos.x, pos.y);
context.lineTo(posChild.x, posChild.y);
});
};
GraphPlot.getLabelContainer = function(controller){
return document.getElementById(controller.getNodeLabelContainer());
};
GraphPlot.fitsInCanvas= function(pos, canvas) {
//canvas.setPosition();
var size = canvas.getSize();
var offset1 = parseInt(size.x);
var offset2 = parseInt(size.y);
if(pos.x < 0 || pos.x > offset1 || pos.y < 0 || pos.y > offset2) return false;
else
return true;
};
GraphPlot.plotLabel= function(canvas, node, controller) {
var size = node._radius;
var id = controller.getNodeLabelPrefix() + node.id;//jon change
var d = controller.getOffset(); //jon
var pos = node.pos.toComplex();
var radius= canvas.getSize();
canvas.setPosition(); //jon
var cpos = canvas.getPosition();
var labelPos= {
x: Math.round((pos.x + radius.x/2 - size /2) +d.x),//jon
y: Math.round((pos.y + radius.y/2 - size /2) +d.y)//jon
};
var tag = this.getLabel(id);
if(!this.fitsInCanvas(labelPos,canvas)) {
//if(tag && tag.parentNode)tag.parentNode.removeChild(tag);
return;
}
if(!tag && !(tag = document.getElementById(id))) {
tag = document.createElement('div');
var container = this.getLabelContainer(controller); //jon change
container.style.position= 'relative';//jon change
container.appendChild(tag);
tag.id = id;
tag.className = 'node';
tag.style.position = 'absolute';
controller.onCreateLabel(tag, node);
}
tag.style.width = size + 'px';
tag.style.height = size + 'px';
tag.style.left = labelPos.x + 'px';
tag.style.top = labelPos.y + 'px';
tag.style.display = this.fitsInCanvas(labelPos, canvas)? '' : 'none';
controller.onPlaceLabel(tag, node);
};
/*overriding of several functions */
GraphPlot.plotNode = function(node, canvas,controller) {
var pos = node.pos.toComplex();
var d = controller.getOffset();
if(node.data.nodraw == undefined) //jon
canvas.path('fill', function(context) {
context.arc(pos.x +d.x, pos.y +d.y, node._radius, 0, Math.PI*2, true); //jon
});
};
GraphPlot.plot= function(viz, opt) {
var aGraph = viz.graph, canvas = viz.canvas, id = viz.root;
var controller = viz.controller;//jon
var container = this.getLabelContainer(controller); //jon change
container.innerHTML = "";
var that = this, ctx = canvas.getContext(), GUtil = GraphUtil;
canvas.clear();
if(Config.drawConcentricCircles) canvas.drawConcentricCircles(Config.drawConcentricCircles);
var T = !!aGraph.getNode(id).visited;
GUtil.eachNode(aGraph, function(node) {
GUtil.eachAdjacency(node, function(adj) {
if(!!adj.nodeTo.visited === T) {
opt.onBeforePlotLine(adj);
ctx.save();
ctx.globalAlpha = Math.min(Math.min(node.alpha, adj.nodeTo.alpha), adj.alpha);
that.plotLine(adj, canvas,controller);//jon
ctx.restore();
opt.onAfterPlotLine(adj);
}
});
ctx.save();
ctx.globalAlpha = node.alpha;
that.plotNode(node, canvas,controller); //jon
if(!that.labelsHidden && ctx.globalAlpha >= .95) that.plotLabel(canvas, node, opt);
else if(!that.labelsHidden && ctx.globalAlpha < .95) that.hideLabel(node);
ctx.restore();
node.visited = !T;
});
};
/***
!Layer 4: Support Internet Explorer (Safely remove if not required)
***/
// Copyright 2006 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Known Issues:
//
// * Patterns are not implemented.
// * Radial gradient are not implemented. The VML version of these look very
// different from the canvas one.
// * Clipping paths are not implemented.
// * Coordsize. The width and height attribute have higher priority than the
// width and height style values which isn't correct.
// * Painting mode isn't implemented.
// * Canvas width/height should is using content-box by default. IE in
// Quirks mode will draw the canvas using border-box. Either change your
// doctype to HTML5
// (http://www.whatwg.org/specs/web-apps/current-work/#the-doctype)
// or use Box Sizing Behavior from WebFX
// (http://webfx.eae.net/dhtml/boxsizing/boxsizing.html)
// * Non uniform scaling does not correctly scale strokes.
// * Optimize. There is always room for speed improvements.
// Only add this code if we do not already have a canvas implementation
if(!document.createElement('canvas').getContext){(function(){var m=Math;var mr=m.round;var ms=m.sin;var mc=m.cos;var max=m.max;var abs=m.abs;var sqrt=m.sqrt;var Z=10;var Z2=Z/2;function getContext(){return this.context_||(this.context_=new CanvasRenderingContext2D_(this))}var slice=Array.prototype.slice;function bind(f,obj,var_args){var a=slice.call(arguments,2);return function(){return f.apply(obj,a.concat(slice.call(arguments)))}}var G_vmlCanvasManager_={init:function(opt_doc){if(/MSIE/.test(navigator.userAgent)&&!window.opera){var doc=opt_doc||document;doc.createElement('canvas');doc.attachEvent('onreadystatechange',bind(this.init_,this,doc))}},init_:function(doc){if(!doc.namespaces['g_vml_']){doc.namespaces.add('g_vml_','urn:schemas-microsoft-com:vml')}if(!doc.styleSheets['ex_canvas_']){var ss=doc.createStyleSheet();ss.owningElement.id='ex_canvas_';ss.cssText='canvas{display:inline-block;overflow:hidden;'+'text-align:left;width:300px;height:150px}'+'g_vml_\\:*{behavior:url(#default#VML)}'}var els=doc.getElementsByTagName('canvas');for(var i=0;i<els.length;i++){this.initElement(els[i])}},initElement:function(el){if(!el.getContext){el.getContext=getContext;el.attachEvent('onpropertychange',onPropertyChange);el.attachEvent('onresize',onResize);var attrs=el.attributes;if(attrs.width&&attrs.width.specified){el.style.width=attrs.width.nodeValue+'px'}else{el.width=el.clientWidth}if(attrs.height&&attrs.height.specified){el.style.height=attrs.height.nodeValue+'px'}else{el.height=el.clientHeight}}return el}};function onPropertyChange(e){var el=e.srcElement;switch(e.propertyName){case'width':el.style.width=el.attributes.width.nodeValue+'px';el.getContext().clearRect();break;case'height':el.style.height=el.attributes.height.nodeValue+'px';el.getContext().clearRect();break}}function onResize(e){var el=e.srcElement;if(el.firstChild){el.firstChild.style.width=el.clientWidth+'px';el.firstChild.style.height=el.clientHeight+'px'}}G_vmlCanvasManager_.init();var dec2hex=[];for(var i=0;i<16;i++){for(var j=0;j<16;j++){dec2hex[i*16+j]=i.toString(16)+j.toString(16)}}function createMatrixIdentity(){return[[1,0,0],[0,1,0],[0,0,1]]}function matrixMultiply(m1,m2){var result=createMatrixIdentity();for(var x=0;x<3;x++){for(var y=0;y<3;y++){var sum=0;for(var z=0;z<3;z++){sum+=m1[x][z]*m2[z][y]}result[x][y]=sum}}return result}function copyState(o1,o2){o2.fillStyle=o1.fillStyle;o2.lineCap=o1.lineCap;o2.lineJoin=o1.lineJoin;o2.lineWidth=o1.lineWidth;o2.miterLimit=o1.miterLimit;o2.shadowBlur=o1.shadowBlur;o2.shadowColor=o1.shadowColor;o2.shadowOffsetX=o1.shadowOffsetX;o2.shadowOffsetY=o1.shadowOffsetY;o2.strokeStyle=o1.strokeStyle;o2.globalAlpha=o1.globalAlpha;o2.arcScaleX_=o1.arcScaleX_;o2.arcScaleY_=o1.arcScaleY_;o2.lineScale_=o1.lineScale_}function processStyle(styleString){var str,alpha=1;styleString=String(styleString);if(styleString.substring(0,3)=='rgb'){var start=styleString.indexOf('(',3);var end=styleString.indexOf(')',start+1);var guts=styleString.substring(start+1,end).split(',');str='#';for(var i=0;i<3;i++){str+=dec2hex[Number(guts[i])]}if(guts.length==4&&styleString.substr(3,1)=='a'){alpha=guts[3]}}else{str=styleString}return[str,alpha]}function processLineCap(lineCap){switch(lineCap){case'butt':return'flat';case'round':return'round';case'square':default:return'square'}}function CanvasRenderingContext2D_(surfaceElement){this.m_=createMatrixIdentity();this.mStack_=[];this.aStack_=[];this.currentPath_=[];this.strokeStyle='#000';this.fillStyle='#000';this.lineWidth=1;this.lineJoin='miter';this.lineCap='butt';this.miterLimit=Z*1;this.globalAlpha=1;this.canvas=surfaceElement;var el=surfaceElement.ownerDocument.createElement('div');el.style.width=surfaceElement.clientWidth+'px';el.style.height=surfaceElement.clientHeight+'px';el.style.overflow='hidden';el.style.position='absolute';surfaceElement.appendChild(el);this.element_=el;this.arcScaleX_=1;this.arcScaleY_=1;this.lineScale_=1}var contextPrototype=CanvasRenderingContext2D_.prototype;contextPrototype.clearRect=function(){this.element_.innerHTML='';this.currentPath_=[]};contextPrototype.beginPath=function(){this.currentPath_=[]};contextPrototype.moveTo=function(aX,aY){var p=this.getCoords_(aX,aY);this.currentPath_.push({type:'moveTo',x:p.x,y:p.y});this.currentX_=p.x;this.currentY_=p.y};contextPrototype.lineTo=function(aX,aY){var p=this.getCoords_(aX,aY);this.currentPath_.push({type:'lineTo',x:p.x,y:p.y});this.currentX_=p.x;this.currentY_=p.y};contextPrototype.bezierCurveTo=function(aCP1x,aCP1y,aCP2x,aCP2y,aX,aY){var p=this.getCoords_(aX,aY);var cp1=this.getCoords_(aCP1x,aCP1y);var cp2=this.getCoords_(aCP2x,aCP2y);bezierCurveTo(this,cp1,cp2,p)};function bezierCurveTo(self,cp1,cp2,p){self.currentPath_.push({type:'bezierCurveTo',cp1x:cp1.x,cp1y:cp1.y,cp2x:cp2.x,cp2y:cp2.y,x:p.x,y:p.y});self.currentX_=p.x;self.currentY_=p.y}contextPrototype.quadraticCurveTo=function(aCPx,aCPy,aX,aY){var cp=this.getCoords_(aCPx,aCPy);var p=this.getCoords_(aX,aY);var cp1={x:this.currentX_+2.0/3.0*(cp.x-this.currentX_),y:this.currentY_+2.0/3.0*(cp.y-this.currentY_)};var cp2={x:cp1.x+(p.x-this.currentX_)/3.0,y:cp1.y+(p.y-this.currentY_)/3.0};bezierCurveTo(this,cp1,cp2,p)};contextPrototype.arc=function(aX,aY,aRadius,aStartAngle,aEndAngle,aClockwise){aRadius*=Z;var arcType=aClockwise?'at':'wa';var xStart=aX+mc(aStartAngle)*aRadius-Z2;var yStart=aY+ms(aStartAngle)*aRadius-Z2;var xEnd=aX+mc(aEndAngle)*aRadius-Z2;var yEnd=aY+ms(aEndAngle)*aRadius-Z2;if(xStart==xEnd&&!aClockwise){xStart+=0.125}var p=this.getCoords_(aX,aY);var pStart=this.getCoords_(xStart,yStart);var pEnd=this.getCoords_(xEnd,yEnd);this.currentPath_.push({type:arcType,x:p.x,y:p.y,radius:aRadius,xStart:pStart.x,yStart:pStart.y,xEnd:pEnd.x,yEnd:pEnd.y})};contextPrototype.rect=function(aX,aY,aWidth,aHeight){this.moveTo(aX,aY);this.lineTo(aX+aWidth,aY);this.lineTo(aX+aWidth,aY+aHeight);this.lineTo(aX,aY+aHeight);this.closePath()};contextPrototype.strokeRect=function(aX,aY,aWidth,aHeight){this.beginPath();this.moveTo(aX,aY);this.lineTo(aX+aWidth,aY);this.lineTo(aX+aWidth,aY+aHeight);this.lineTo(aX,aY+aHeight);this.closePath();this.stroke();this.currentPath_=[]};contextPrototype.fillRect=function(aX,aY,aWidth,aHeight){this.beginPath();this.moveTo(aX,aY);this.lineTo(aX+aWidth,aY);this.lineTo(aX+aWidth,aY+aHeight);this.lineTo(aX,aY+aHeight);this.closePath();this.fill();this.currentPath_=[]};contextPrototype.createLinearGradient=function(aX0,aY0,aX1,aY1){return new CanvasGradient_('gradient')};contextPrototype.createRadialGradient=function(aX0,aY0,aR0,aX1,aY1,aR1){var gradient=new CanvasGradient_('gradientradial');gradient.radius1_=aR0;gradient.radius2_=aR1;gradient.focus_.x=aX0;gradient.focus_.y=aY0;return gradient};contextPrototype.drawImage=function(image,var_args){var dx,dy,dw,dh,sx,sy,sw,sh;var oldRuntimeWidth=image.runtimeStyle.width;var oldRuntimeHeight=image.runtimeStyle.height;image.runtimeStyle.width='auto';image.runtimeStyle.height='auto';var w=image.width;var h=image.height;image.runtimeStyle.width=oldRuntimeWidth;image.runtimeStyle.height=oldRuntimeHeight;if(arguments.length==3){dx=arguments[1];dy=arguments[2];sx=sy=0;sw=dw=w;sh=dh=h}else if(arguments.length==5){dx=arguments[1];dy=arguments[2];dw=arguments[3];dh=arguments[4];sx=sy=0;sw=w;sh=h}else if(arguments.length==9){sx=arguments[1];sy=arguments[2];sw=arguments[3];sh=arguments[4];dx=arguments[5];dy=arguments[6];dw=arguments[7];dh=arguments[8]}else{throw Error('Invalid number of arguments');}var d=this.getCoords_(dx,dy);var w2=sw/2;var h2=sh/2;var vmlStr=[];var W=10;var H=10;vmlStr.push(' <g_vml_:group',' coordsize="',Z*W,',',Z*H,'"',' coordorigin="0,0"',' style="width:',W,';height:',H,';position:absolute;');if(this.m_[0][0]!=1||this.m_[0][1]){var filter=[];filter.push('M11=',this.m_[0][0],',','M12=',this.m_[1][0],',','M21=',this.m_[0][1],',','M22=',this.m_[1][1],',','Dx=',mr(d.x/Z),',','Dy=',mr(d.y/Z),'');var max=d;var c2=this.getCoords_(dx+dw,dy);var c3=this.getCoords_(dx,dy+dh);var c4=this.getCoords_(dx+dw,dy+dh);max.x=max(max.x,c2.x,c3.x,c4.x);max.y=max(max.y,c2.y,c3.y,c4.y);vmlStr.push('padding:0 ',mr(max.x/Z),'px ',mr(max.y/Z),'px 0;filter:progid:DXImageTransform.Microsoft.Matrix(',filter.join(''),", sizingmethod='clip');")}else{vmlStr.push('top:',mr(d.y/Z),'px;left:',mr(d.x/Z),'px;')}vmlStr.push(' ">','<g_vml_:image src="',image.src,'"',' style="width:',Z*dw,';',' height:',Z*dh,';"',' cropleft="',sx/w,'"',' croptop="',sy/h,'"',' cropright="',(w-sx-sw)/w,'"',' cropbottom="',(h-sy-sh)/h,'"',' />','</g_vml_:group>');this.element_.insertAdjacentHTML('BeforeEnd',vmlStr.join(''))};contextPrototype.stroke=function(aFill){var lineStr=[];var lineOpen=false;var a=processStyle(aFill?this.fillStyle:this.strokeStyle);var color=a[0];var opacity=a[1]*this.globalAlpha;var W=10;var H=10;lineStr.push('<g_vml_:shape',' filled="',!!aFill,'"',' style="position:absolute;width:',W,';height:',H,';"',' coordorigin="0 0" coordsize="',Z*W,' ',Z*H,'"',' stroked="',!aFill,'"',' path="');var newSeq=false;var min={x:null,y:null};var max={x:null,y:null};for(var i=0;i<this.currentPath_.length;i++){var p=this.currentPath_[i];var c;switch(p.type){case'moveTo':c=p;lineStr.push(' m ',mr(p.x),',',mr(p.y));break;case'lineTo':lineStr.push(' l ',mr(p.x),',',mr(p.y));break;case'close':lineStr.push(' x ');p=null;break;case'bezierCurveTo':lineStr.push(' c ',mr(p.cp1x),',',mr(p.cp1y),',',mr(p.cp2x),',',mr(p.cp2y),',',mr(p.x),',',mr(p.y));break;case'at':case'wa':lineStr.push(' ',p.type,' ',mr(p.x-this.arcScaleX_*p.radius),',',mr(p.y-this.arcScaleY_*p.radius),' ',mr(p.x+this.arcScaleX_*p.radius),',',mr(p.y+this.arcScaleY_*p.radius),' ',mr(p.xStart),',',mr(p.yStart),' ',mr(p.xEnd),',',mr(p.yEnd));break}if(p){if(min.x==null||p.x<min.x){min.x=p.x}if(max.x==null||p.x>max.x){max.x=p.x}if(min.y==null||p.y<min.y){min.y=p.y}if(max.y==null||p.y>max.y){max.y=p.y}}}lineStr.push(' ">');if(!aFill){var lineWidth=this.lineScale_*this.lineWidth;if(lineWidth<1){opacity*=lineWidth}lineStr.push('<g_vml_:stroke',' opacity="',opacity,'"',' joinstyle="',this.lineJoin,'"',' miterlimit="',this.miterLimit,'"',' endcap="',processLineCap(this.lineCap),'"',' weight="',lineWidth,'px"',' color="',color,'" />')}else if(typeof this.fillStyle=='object'){var focus={x:'50%',y:'50%'};var width=max.x-min.x;var height=max.y-min.y;var dimension=width>height?width:height;focus.x=mr(this.fillStyle.focus_.x/width*100+50)+'%';focus.y=mr(this.fillStyle.focus_.y/height*100+50)+'%';var colors=[];if(this.fillStyle.type_=='gradientradial'){var inside=this.fillStyle.radius1_/dimension*100;var expansion=this.fillStyle.radius2_/dimension*100-inside}else{var inside=0;var expansion=100}var insidecolor={offset:null,color:null};var outsidecolor={offset:null,color:null};this.fillStyle.colors_.sort(function(cs1,cs2){return cs1.offset-cs2.offset});for(var i=0;i<this.fillStyle.colors_.length;i++){var fs=this.fillStyle.colors_[i];colors.push(fs.offset*expansion+inside,'% ',fs.color,',');if(fs.offset>insidecolor.offset||insidecolor.offset==null){insidecolor.offset=fs.offset;insidecolor.color=fs.color}if(fs.offset<outsidecolor.offset||outsidecolor.offset==null){outsidecolor.offset=fs.offset;outsidecolor.color=fs.color}}colors.pop();lineStr.push('<g_vml_:fill',' color="',outsidecolor.color,'"',' color2="',insidecolor.color,'"',' type="',this.fillStyle.type_,'"',' focusposition="',focus.x,', ',focus.y,'"',' colors="',colors.join(''),'"',' opacity="',opacity,'" />')}else{lineStr.push('<g_vml_:fill color="',color,'" opacity="',opacity,'" />')}lineStr.push('</g_vml_:shape>');this.element_.insertAdjacentHTML('beforeEnd',lineStr.join(''))};contextPrototype.fill=function(){this.stroke(true)};contextPrototype.closePath=function(){this.currentPath_.push({type:'close'})};contextPrototype.getCoords_=function(aX,aY){var m=this.m_;return{x:Z*(aX*m[0][0]+aY*m[1][0]+m[2][0])-Z2,y:Z*(aX*m[0][1]+aY*m[1][1]+m[2][1])-Z2}};contextPrototype.save=function(){var o={};copyState(this,o);this.aStack_.push(o);this.mStack_.push(this.m_);this.m_=matrixMultiply(createMatrixIdentity(),this.m_)};contextPrototype.restore=function(){copyState(this.aStack_.pop(),this);this.m_=this.mStack_.pop()};contextPrototype.translate=function(aX,aY){var m1=[[1,0,0],[0,1,0],[aX,aY,1]];this.m_=matrixMultiply(m1,this.m_)};contextPrototype.rotate=function(aRot){var c=mc(aRot);var s=ms(aRot);var m1=[[c,s,0],[-s,c,0],[0,0,1]];this.m_=matrixMultiply(m1,this.m_)};contextPrototype.scale=function(aX,aY){this.arcScaleX_*=aX;this.arcScaleY_*=aY;var m1=[[aX,0,0],[0,aY,0],[0,0,1]];var m=this.m_=matrixMultiply(m1,this.m_);var det=m[0][0]*m[1][1]-m[0][1]*m[1][0];this.lineScale_=sqrt(abs(det))};contextPrototype.clip=function(){};contextPrototype.arcTo=function(){};contextPrototype.createPattern=function(){return new CanvasPattern_};function CanvasGradient_(aType){this.type_=aType;this.radius1_=0;this.radius2_=0;this.colors_=[];this.focus_={x:0,y:0}}CanvasGradient_.prototype.addColorStop=function(aOffset,aColor){aColor=processStyle(aColor);this.colors_.push({offset:1-aOffset,color:aColor})};function CanvasPattern_(){}G_vmlCanvasManager=G_vmlCanvasManager_;CanvasRenderingContext2D=CanvasRenderingContext2D_;CanvasGradient=CanvasGradient_;CanvasPattern=CanvasPattern_})()}
!¿Qué es un TiddlyWiki?
!!Descripción técnica
Es un wiki hecho en Javascript, en un solo fichero.
En la [[página oficial|http://www.tiddlywiki.com]] se define como “un bloc de notas web, reusable, personal y no-lineal“.
!!Descripción no-técnica
Un TW es un tipo de archivo que sirve para muchas cosas, y constantemente se le encuentran nuevos usos. Puede hacerse una presentación, un blog, un libro, una “base de datos”, un bloc de notas, una agenda, una lista de tareas pendientes, o mezclas de estas cosas. Todo queda incluído en un único archivo o fichero HTML.
En general, está relacionado con el tratamiento de pequeñas cantidades de información (textos) interconectadas, que reciben el nombre de "tiddlers" o "micro-contenidos".
!!Características
* Tiene un único fichero o archivo
* sintaxis wiki (como [[wikipedia|http://www.wikipedia.org]])
* micro-contenido (tiddlers)
* etiquetas
* busqueda integrada
* extensible
* sobre formato web
* y es software libre (BSD, Licencia de Código abierto)
!!Manejo del Archivo
Un archivo TiddlyWiki se descarga, se edita progresivamente, y puede ser guardado en el computador, en un pendrive USB, o en algún sitio web, y puedes ser enviado por correo electrónico.
Es el tiempo que tarda el hechicero o místico en lograr que un hechizo empiece a tener efectos. Durante ese tiempo el personaje realiza el esfuerzo requerido para canalizar la "energía mágica", mediante cánticos, palabras, trazado de símbolos, danza, sacrificios, rituales, o simplemente meditando.
Mientras más tiempo se toma el personaje invocando el hechizo, el costo "mágico" y la dificultad del mismo disminuyen. Por ejemplo, es más fácil realizar un hechizo luego de media hora de invocación, que hacerlo de forma instantánea.
/***
|Name|ToggleSideBarMacro|
|Created by|SaqImtiaz|
|Location|http://tw.lewcid.org/#ToggleSideBarMacro|
|Version|1.0|
|Requires|~TW2.x|
!Description:
Provides a button for toggling visibility of the SideBar. You can choose whether the SideBar should initially be hidden or displayed.
!Demo
<<toggleSideBar "Toggle Sidebar">>
!Usage:
{{{<<toggleSideBar>>}}} <<toggleSideBar>>
additional options:
{{{<<toggleSideBar label tooltip show/hide>>}}} where:
label = custom label for the button,
tooltip = custom tooltip for the button,
show/hide = use one or the other, determines whether the sidebar is shown at first or not.
(default is to show the sidebar)
You can add it to your tiddler toolbar, your MainMenu, or where you like really.
If you are using a horizontal MainMenu and want the button to be right aligned, put the following in your StyleSheet:
{{{ .HideSideBarButton {float:right;} }}}
!History
*23-07-06: version 1.0: completely rewritten, now works with custom stylesheets too, and easier to customize start behaviour.
*20-07-06: version 0.11
*27-04-06: version 0.1: working.
!Code
***/
//{{{
config.macros.toggleSideBar={};
config.macros.toggleSideBar.settings={
styleHide : "#sidebar { display: none;}\n"+"#contentWrapper #displayArea { margin-right: 1em;}\n"+"",
styleShow : " ",
arrow1: "«",
arrow2: "»"
};
config.macros.toggleSideBar.handler=function (place,macroName,params,wikifier,paramString,tiddler)
{
var tooltip= params[1]||'toggle sidebar';
var mode = (params[2] && params[2]=="hide")? "hide":"show";
var arrow = (mode == "hide")? this.settings.arrow1:this.settings.arrow2;
var label= (params[0]&¶ms[0]!='.')?params[0]+" "+arrow:arrow;
var theBtn = createTiddlyButton(place,label,tooltip,this.onToggleSideBar,"button HideSideBarButton");
if (mode == "hide")
{
(document.getElementById("sidebar")).setAttribute("toggle","hide");
setStylesheet(this.settings.styleHide,"ToggleSideBarStyles");
}
};
config.macros.toggleSideBar.onToggleSideBar = function(){
var sidebar = document.getElementById("sidebar");
var settings = config.macros.toggleSideBar.settings;
if (sidebar.getAttribute("toggle")=='hide')
{
setStylesheet(settings.styleShow,"ToggleSideBarStyles");
sidebar.setAttribute("toggle","show");
this.firstChild.data= (this.firstChild.data).replace(settings.arrow1,settings.arrow2);
}
else
{
setStylesheet(settings.styleHide,"ToggleSideBarStyles");
sidebar.setAttribute("toggle","hide");
this.firstChild.data= (this.firstChild.data).replace(settings.arrow2,settings.arrow1);
}
return false;
}
setStylesheet(".HideSideBarButton .button {font-weight:bold; padding: 0 5px;}\n","ToggleSideBarButtonStyles");
//}}}
/***
|Name:|ToggleTagPlugin|
|Description:|Makes a checkbox which toggles a tag in a tiddler|
|Version:|3.1.0 ($Rev: 4907 $)|
|Date:|$Date: 2008-05-13 03:15:46 +1000 (Tue, 13 May 2008) $|
|Source:|http://mptw.tiddlyspot.com/#ToggleTagPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License:|http://mptw.tiddlyspot.com/#TheBSDLicense|
!!Usage
{{{<<toggleTag }}}//{{{TagName TiddlerName LabelText}}}//{{{>>}}}
* TagName - the tag to be toggled, default value "checked"
* TiddlerName - the tiddler to toggle the tag in, default value the current tiddler
* LabelText - the text (gets wikified) to put next to the check box, default value is '{{{[[TagName]]}}}' or '{{{[[TagName]] [[TiddlerName]]}}}'
(If a parameter is '.' then the default will be used)
* TouchMod flag - if non empty then touch the tiddlers mod date. Note, can set config.toggleTagAlwaysTouchModDate to always touch mod date
!!Examples
|Code|Description|Example|h
|{{{<<toggleTag>>}}}|Toggles the default tag (checked) in this tiddler|<<toggleTag>>|
|{{{<<toggleTag TagName>>}}}|Toggles the TagName tag in this tiddler|<<toggleTag TagName>>|
|{{{<<toggleTag TagName TiddlerName>>}}}|Toggles the TagName tag in the TiddlerName tiddler|<<toggleTag TagName TiddlerName>>|
|{{{<<toggleTag TagName TiddlerName 'click me'>>}}}|Same but with custom label|<<toggleTag TagName TiddlerName 'click me'>>|
|{{{<<toggleTag . . 'click me'>>}}}|dot means use default value|<<toggleTag . . 'click me'>>|
!!Notes
* If TiddlerName doesn't exist it will be silently created
* Set label to '-' to specify no label
* See also http://mgtd-alpha.tiddlyspot.com/#ToggleTag2
!!Known issues
* Doesn't smoothly handle the case where you toggle a tag in a tiddler that is current open for editing
* Should convert to use named params
***/
//{{{
if (config.toggleTagAlwaysTouchModDate == undefined) config.toggleTagAlwaysTouchModDate = false;
merge(config.macros,{
toggleTag: {
createIfRequired: true,
shortLabel: "[[%0]]",
longLabel: "[[%0]] [[%1]]",
handler: function(place,macroName,params,wikifier,paramString,tiddler) {
var tiddlerTitle = tiddler ? tiddler.title : '';
var tag = (params[0] && params[0] != '.') ? params[0] : "checked";
var title = (params[1] && params[1] != '.') ? params[1] : tiddlerTitle;
var defaultLabel = (title == tiddlerTitle ? this.shortLabel : this.longLabel);
var label = (params[2] && params[2] != '.') ? params[2] : defaultLabel;
var touchMod = (params[3] && params[3] != '.') ? params[3] : "";
label = (label == '-' ? '' : label); // dash means no label
var theTiddler = (title == tiddlerTitle ? tiddler : store.getTiddler(title));
var cb = createTiddlyCheckbox(place, label.format([tag,title]), theTiddler && theTiddler.isTagged(tag), function(e) {
if (!store.tiddlerExists(title)) {
if (config.macros.toggleTag.createIfRequired) {
var content = store.getTiddlerText(title); // just in case it's a shadow
store.saveTiddler(title,title,content?content:"",config.options.txtUserName,new Date(),null);
}
else
return false;
}
if ((touchMod != "" || config.toggleTagAlwaysTouchModDate) && theTiddler)
theTiddler.modified = new Date();
store.setTiddlerTag(title,this.checked,tag);
return true;
});
}
}
});
//}}}
/***
Description: Contains the stuff you need to use Tiddlyspot
Note, you also need UploadPlugin, PasswordOptionPlugin and LoadRemoteFileThroughProxy
from http://tiddlywiki.bidix.info for a complete working Tiddlyspot site.
***/
//{{{
// edit this if you are migrating sites or retrofitting an existing TW
config.tiddlyspotSiteId = 'sagapedia';
// make it so you can by default see edit controls via http
config.options.chkHttpReadOnly = false;
window.readOnly = false; // make sure of it (for tw 2.2)
window.showBackstage = true; // show backstage too
// disable autosave in d3
if (window.location.protocol != "file:")
config.options.chkGTDLazyAutoSave = false;
// tweak shadow tiddlers to add upload button, password entry box etc
with (config.shadowTiddlers) {
SiteUrl = 'http://'+config.tiddlyspotSiteId+'.tiddlyspot.com';
SideBarOptions = SideBarOptions.replace(/(<<saveChanges>>)/,"$1<<tiddler TspotSidebar>>");
OptionsPanel = OptionsPanel.replace(/^/,"<<tiddler TspotOptions>>");
DefaultTiddlers = DefaultTiddlers.replace(/^/,"[[WelcomeToTiddlyspot]] ");
MainMenu = MainMenu.replace(/^/,"[[WelcomeToTiddlyspot]] ");
}
// create some shadow tiddler content
merge(config.shadowTiddlers,{
'WelcomeToTiddlyspot':[
"This document is a ~TiddlyWiki from tiddlyspot.com. A ~TiddlyWiki is an electronic notebook that is great for managing todo lists, personal information, and all sorts of things.",
"",
"@@font-weight:bold;font-size:1.3em;color:#444; //What now?// @@ Before you can save any changes, you need to enter your password in the form below. Then configure privacy and other site settings at your [[control panel|http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/controlpanel]] (your control panel username is //" + config.tiddlyspotSiteId + "//).",
"<<tiddler TspotControls>>",
"See also GettingStarted.",
"",
"@@font-weight:bold;font-size:1.3em;color:#444; //Working online// @@ You can edit this ~TiddlyWiki right now, and save your changes using the \"save to web\" button in the column on the right.",
"",
"@@font-weight:bold;font-size:1.3em;color:#444; //Working offline// @@ A fully functioning copy of this ~TiddlyWiki can be saved onto your hard drive or USB stick. You can make changes and save them locally without being connected to the Internet. When you're ready to sync up again, just click \"upload\" and your ~TiddlyWiki will be saved back to tiddlyspot.com.",
"",
"@@font-weight:bold;font-size:1.3em;color:#444; //Help!// @@ Find out more about ~TiddlyWiki at [[TiddlyWiki.com|http://tiddlywiki.com]]. Also visit [[TiddlyWiki.org|http://tiddlywiki.org]] for documentation on learning and using ~TiddlyWiki. New users are especially welcome on the [[TiddlyWiki mailing list|http://groups.google.com/group/TiddlyWiki]], which is an excellent place to ask questions and get help. If you have a tiddlyspot related problem email [[tiddlyspot support|mailto:support@tiddlyspot.com]].",
"",
"@@font-weight:bold;font-size:1.3em;color:#444; //Enjoy :)// @@ We hope you like using your tiddlyspot.com site. Please email [[feedback@tiddlyspot.com|mailto:feedback@tiddlyspot.com]] with any comments or suggestions."
].join("\n"),
'TspotControls':[
"| tiddlyspot password:|<<option pasUploadPassword>>|",
"| site management:|<<upload http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/store.cgi index.html . . " + config.tiddlyspotSiteId + ">>//(requires tiddlyspot password)//<br>[[control panel|http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/controlpanel]], [[download (go offline)|http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/download]]|",
"| links:|[[tiddlyspot.com|http://tiddlyspot.com/]], [[FAQs|http://faq.tiddlyspot.com/]], [[blog|http://tiddlyspot.blogspot.com/]], email [[support|mailto:support@tiddlyspot.com]] & [[feedback|mailto:feedback@tiddlyspot.com]], [[donate|http://tiddlyspot.com/?page=donate]]|"
].join("\n"),
'TspotSidebar':[
"<<upload http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/store.cgi index.html . . " + config.tiddlyspotSiteId + ">><html><a href='http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/download' class='button'>download</a></html>"
].join("\n"),
'TspotOptions':[
"tiddlyspot password:",
"<<option pasUploadPassword>>",
""
].join("\n")
});
//}}}
| !date | !user | !location | !storeUrl | !uploadDir | !toFilename | !backupdir | !origin |
| 16/05/2012 11:46:09 | OManzanilla | [[/|http://sagapedia.tiddlyspot.com/]] | [[store.cgi|http://sagapedia.tiddlyspot.com/store.cgi]] | . | [[index.html | http://sagapedia.tiddlyspot.com/index.html]] | . |
| 16/05/2012 11:47:05 | OManzanilla | [[/|http://sagapedia.tiddlyspot.com/]] | [[store.cgi|http://sagapedia.tiddlyspot.com/store.cgi]] | . | [[index.html | http://sagapedia.tiddlyspot.com/index.html]] | . |
| 16/05/2012 11:48:45 | OManzanilla | [[/|http://sagapedia.tiddlyspot.com/]] | [[store.cgi|http://sagapedia.tiddlyspot.com/store.cgi]] | . | [[index.html | http://sagapedia.tiddlyspot.com/index.html]] | . |
| 17/05/2012 00:50:12 | OManzanilla | [[index.20120516.0942400000.html|http://sagapedia.tiddlyspot.com/backup/index.20120516.0942400000.html]] | [[store.cgi|http://sagapedia.tiddlyspot.com/store.cgi]] | . | [[index.html | http://sagapedia.tiddlyspot.com/index.html]] | . |
| 01/07/2012 19:37:26 | OManzanilla | [[/|http://sagapedia.tiddlyspot.com/]] | [[store.cgi|http://sagapedia.tiddlyspot.com/store.cgi]] | . | [[index.html | http://sagapedia.tiddlyspot.com/index.html]] | . | ok |
| 01/07/2012 20:39:45 | OManzanilla | [[/|http://sagapedia.tiddlyspot.com/]] | [[store.cgi|http://sagapedia.tiddlyspot.com/store.cgi]] | . | [[index.html | http://sagapedia.tiddlyspot.com/index.html]] | . |
| 30/10/2013 11:06:48 | OManzanilla | [[/|http://sagapedia.tiddlyspot.com/#%5B%5BLectura%20de%20Personajes%20de%20Cartas%5D%5D]] | [[store.cgi|http://sagapedia.tiddlyspot.com/store.cgi]] | . | [[index.html | http://sagapedia.tiddlyspot.com/index.html]] | . | ok |
| 30/10/2013 11:39:30 | OManzanilla | [[/|http://sagapedia.tiddlyspot.com/#%5B%5BLectura%20de%20Personajes%20de%20Cartas%5D%5D]] | [[store.cgi|http://sagapedia.tiddlyspot.com/store.cgi]] | . | [[index.html | http://sagapedia.tiddlyspot.com/index.html]] | . |
| 22/11/2013 10:40:31 | OManzanilla | [[/|http://sagapedia.tiddlyspot.com/]] | [[store.cgi|http://sagapedia.tiddlyspot.com/store.cgi]] | . | [[index.html | http://sagapedia.tiddlyspot.com/index.html]] | . |
| 28/02/2017 14:12:20 | OManzanilla | [[/|http://sagapedia.tiddlyspot.com/]] | [[store.cgi|http://sagapedia.tiddlyspot.com/store.cgi]] | . | [[index.html | http://sagapedia.tiddlyspot.com/index.html]] | . |
/***
|''Name:''|UploadPlugin|
|''Description:''|Save to web a TiddlyWiki|
|''Version:''|4.1.3|
|''Date:''|Feb 24, 2008|
|''Source:''|http://tiddlywiki.bidix.info/#UploadPlugin|
|''Documentation:''|http://tiddlywiki.bidix.info/#UploadPluginDoc|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0|
|''Requires:''|PasswordOptionPlugin|
***/
//{{{
version.extensions.UploadPlugin = {
major: 4, minor: 1, revision: 3,
date: new Date("Feb 24, 2008"),
source: 'http://tiddlywiki.bidix.info/#UploadPlugin',
author: 'BidiX (BidiX (at) bidix (dot) info',
coreVersion: '2.2.0'
};
//
// Environment
//
if (!window.bidix) window.bidix = {}; // bidix namespace
bidix.debugMode = false; // true to activate both in Plugin and UploadService
//
// Upload Macro
//
config.macros.upload = {
// default values
defaultBackupDir: '', //no backup
defaultStoreScript: "store.php",
defaultToFilename: "index.html",
defaultUploadDir: ".",
authenticateUser: true // UploadService Authenticate User
};
config.macros.upload.label = {
promptOption: "Save and Upload this TiddlyWiki with UploadOptions",
promptParamMacro: "Save and Upload this TiddlyWiki in %0",
saveLabel: "save to web",
saveToDisk: "save to disk",
uploadLabel: "upload"
};
config.macros.upload.messages = {
noStoreUrl: "No store URL in parmeters or options",
usernameOrPasswordMissing: "Username or password missing"
};
config.macros.upload.handler = function(place,macroName,params) {
if (readOnly)
return;
var label;
if (document.location.toString().substr(0,4) == "http")
label = this.label.saveLabel;
else
label = this.label.uploadLabel;
var prompt;
if (params[0]) {
prompt = this.label.promptParamMacro.toString().format([this.destFile(params[0],
(params[1] ? params[1]:bidix.basename(window.location.toString())), params[3])]);
} else {
prompt = this.label.promptOption;
}
createTiddlyButton(place, label, prompt, function() {config.macros.upload.action(params);}, null, null, this.accessKey);
};
config.macros.upload.action = function(params)
{
// for missing macro parameter set value from options
if (!params) params = {};
var storeUrl = params[0] ? params[0] : config.options.txtUploadStoreUrl;
var toFilename = params[1] ? params[1] : config.options.txtUploadFilename;
var backupDir = params[2] ? params[2] : config.options.txtUploadBackupDir;
var uploadDir = params[3] ? params[3] : config.options.txtUploadDir;
var username = params[4] ? params[4] : config.options.txtUploadUserName;
var password = config.options.pasUploadPassword; // for security reason no password as macro parameter
// for still missing parameter set default value
if ((!storeUrl) && (document.location.toString().substr(0,4) == "http"))
storeUrl = bidix.dirname(document.location.toString())+'/'+config.macros.upload.defaultStoreScript;
if (storeUrl.substr(0,4) != "http")
storeUrl = bidix.dirname(document.location.toString()) +'/'+ storeUrl;
if (!toFilename)
toFilename = bidix.basename(window.location.toString());
if (!toFilename)
toFilename = config.macros.upload.defaultToFilename;
if (!uploadDir)
uploadDir = config.macros.upload.defaultUploadDir;
if (!backupDir)
backupDir = config.macros.upload.defaultBackupDir;
// report error if still missing
if (!storeUrl) {
alert(config.macros.upload.messages.noStoreUrl);
clearMessage();
return false;
}
if (config.macros.upload.authenticateUser && (!username || !password)) {
alert(config.macros.upload.messages.usernameOrPasswordMissing);
clearMessage();
return false;
}
bidix.upload.uploadChanges(false,null,storeUrl, toFilename, uploadDir, backupDir, username, password);
return false;
};
config.macros.upload.destFile = function(storeUrl, toFilename, uploadDir)
{
if (!storeUrl)
return null;
var dest = bidix.dirname(storeUrl);
if (uploadDir && uploadDir != '.')
dest = dest + '/' + uploadDir;
dest = dest + '/' + toFilename;
return dest;
};
//
// uploadOptions Macro
//
config.macros.uploadOptions = {
handler: function(place,macroName,params) {
var wizard = new Wizard();
wizard.createWizard(place,this.wizardTitle);
wizard.addStep(this.step1Title,this.step1Html);
var markList = wizard.getElement("markList");
var listWrapper = document.createElement("div");
markList.parentNode.insertBefore(listWrapper,markList);
wizard.setValue("listWrapper",listWrapper);
this.refreshOptions(listWrapper,false);
var uploadCaption;
if (document.location.toString().substr(0,4) == "http")
uploadCaption = config.macros.upload.label.saveLabel;
else
uploadCaption = config.macros.upload.label.uploadLabel;
wizard.setButtons([
{caption: uploadCaption, tooltip: config.macros.upload.label.promptOption,
onClick: config.macros.upload.action},
{caption: this.cancelButton, tooltip: this.cancelButtonPrompt, onClick: this.onCancel}
]);
},
options: [
"txtUploadUserName",
"pasUploadPassword",
"txtUploadStoreUrl",
"txtUploadDir",
"txtUploadFilename",
"txtUploadBackupDir",
"chkUploadLog",
"txtUploadLogMaxLine"
],
refreshOptions: function(listWrapper) {
var opts = [];
for(i=0; i<this.options.length; i++) {
var opt = {};
opts.push();
opt.option = "";
n = this.options[i];
opt.name = n;
opt.lowlight = !config.optionsDesc[n];
opt.description = opt.lowlight ? this.unknownDescription : config.optionsDesc[n];
opts.push(opt);
}
var listview = ListView.create(listWrapper,opts,this.listViewTemplate);
for(n=0; n<opts.length; n++) {
var type = opts[n].name.substr(0,3);
var h = config.macros.option.types[type];
if (h && h.create) {
h.create(opts[n].colElements['option'],type,opts[n].name,opts[n].name,"no");
}
}
},
onCancel: function(e)
{
backstage.switchTab(null);
return false;
},
wizardTitle: "Upload with options",
step1Title: "These options are saved in cookies in your browser",
step1Html: "<input type='hidden' name='markList'></input><br>",
cancelButton: "Cancel",
cancelButtonPrompt: "Cancel prompt",
listViewTemplate: {
columns: [
{name: 'Description', field: 'description', title: "Description", type: 'WikiText'},
{name: 'Option', field: 'option', title: "Option", type: 'String'},
{name: 'Name', field: 'name', title: "Name", type: 'String'}
],
rowClasses: [
{className: 'lowlight', field: 'lowlight'}
]}
};
//
// upload functions
//
if (!bidix.upload) bidix.upload = {};
if (!bidix.upload.messages) bidix.upload.messages = {
//from saving
invalidFileError: "The original file '%0' does not appear to be a valid TiddlyWiki",
backupSaved: "Backup saved",
backupFailed: "Failed to upload backup file",
rssSaved: "RSS feed uploaded",
rssFailed: "Failed to upload RSS feed file",
emptySaved: "Empty template uploaded",
emptyFailed: "Failed to upload empty template file",
mainSaved: "Main TiddlyWiki file uploaded",
mainFailed: "Failed to upload main TiddlyWiki file. Your changes have not been saved",
//specific upload
loadOriginalHttpPostError: "Can't get original file",
aboutToSaveOnHttpPost: 'About to upload on %0 ...',
storePhpNotFound: "The store script '%0' was not found."
};
bidix.upload.uploadChanges = function(onlyIfDirty,tiddlers,storeUrl,toFilename,uploadDir,backupDir,username,password)
{
var callback = function(status,uploadParams,original,url,xhr) {
if (!status) {
displayMessage(bidix.upload.messages.loadOriginalHttpPostError);
return;
}
if (bidix.debugMode)
alert(original.substr(0,500)+"\n...");
// Locate the storeArea div's
var posDiv = locateStoreArea(original);
if((posDiv[0] == -1) || (posDiv[1] == -1)) {
alert(config.messages.invalidFileError.format([localPath]));
return;
}
bidix.upload.uploadRss(uploadParams,original,posDiv);
};
if(onlyIfDirty && !store.isDirty())
return;
clearMessage();
// save on localdisk ?
if (document.location.toString().substr(0,4) == "file") {
var path = document.location.toString();
var localPath = getLocalPath(path);
saveChanges();
}
// get original
var uploadParams = new Array(storeUrl,toFilename,uploadDir,backupDir,username,password);
var originalPath = document.location.toString();
// If url is a directory : add index.html
if (originalPath.charAt(originalPath.length-1) == "/")
originalPath = originalPath + "index.html";
var dest = config.macros.upload.destFile(storeUrl,toFilename,uploadDir);
var log = new bidix.UploadLog();
log.startUpload(storeUrl, dest, uploadDir, backupDir);
displayMessage(bidix.upload.messages.aboutToSaveOnHttpPost.format([dest]));
if (bidix.debugMode)
alert("about to execute Http - GET on "+originalPath);
var r = doHttp("GET",originalPath,null,null,username,password,callback,uploadParams,null);
if (typeof r == "string")
displayMessage(r);
return r;
};
bidix.upload.uploadRss = function(uploadParams,original,posDiv)
{
var callback = function(status,params,responseText,url,xhr) {
if(status) {
var destfile = responseText.substring(responseText.indexOf("destfile:")+9,responseText.indexOf("\n", responseText.indexOf("destfile:")));
displayMessage(bidix.upload.messages.rssSaved,bidix.dirname(url)+'/'+destfile);
bidix.upload.uploadMain(params[0],params[1],params[2]);
} else {
displayMessage(bidix.upload.messages.rssFailed);
}
};
// do uploadRss
if(config.options.chkGenerateAnRssFeed) {
var rssPath = uploadParams[1].substr(0,uploadParams[1].lastIndexOf(".")) + ".xml";
var rssUploadParams = new Array(uploadParams[0],rssPath,uploadParams[2],'',uploadParams[4],uploadParams[5]);
var rssString = generateRss();
// no UnicodeToUTF8 conversion needed when location is "file" !!!
if (document.location.toString().substr(0,4) != "file")
rssString = convertUnicodeToUTF8(rssString);
bidix.upload.httpUpload(rssUploadParams,rssString,callback,Array(uploadParams,original,posDiv));
} else {
bidix.upload.uploadMain(uploadParams,original,posDiv);
}
};
bidix.upload.uploadMain = function(uploadParams,original,posDiv)
{
var callback = function(status,params,responseText,url,xhr) {
var log = new bidix.UploadLog();
if(status) {
// if backupDir specified
if ((params[3]) && (responseText.indexOf("backupfile:") > -1)) {
var backupfile = responseText.substring(responseText.indexOf("backupfile:")+11,responseText.indexOf("\n", responseText.indexOf("backupfile:")));
displayMessage(bidix.upload.messages.backupSaved,bidix.dirname(url)+'/'+backupfile);
}
var destfile = responseText.substring(responseText.indexOf("destfile:")+9,responseText.indexOf("\n", responseText.indexOf("destfile:")));
displayMessage(bidix.upload.messages.mainSaved,bidix.dirname(url)+'/'+destfile);
store.setDirty(false);
log.endUpload("ok");
} else {
alert(bidix.upload.messages.mainFailed);
displayMessage(bidix.upload.messages.mainFailed);
log.endUpload("failed");
}
};
// do uploadMain
var revised = bidix.upload.updateOriginal(original,posDiv);
bidix.upload.httpUpload(uploadParams,revised,callback,uploadParams);
};
bidix.upload.httpUpload = function(uploadParams,data,callback,params)
{
var localCallback = function(status,params,responseText,url,xhr) {
url = (url.indexOf("nocache=") < 0 ? url : url.substring(0,url.indexOf("nocache=")-1));
if (xhr.status == 404)
alert(bidix.upload.messages.storePhpNotFound.format([url]));
if ((bidix.debugMode) || (responseText.indexOf("Debug mode") >= 0 )) {
alert(responseText);
if (responseText.indexOf("Debug mode") >= 0 )
responseText = responseText.substring(responseText.indexOf("\n\n")+2);
} else if (responseText.charAt(0) != '0')
alert(responseText);
if (responseText.charAt(0) != '0')
status = null;
callback(status,params,responseText,url,xhr);
};
// do httpUpload
var boundary = "---------------------------"+"AaB03x";
var uploadFormName = "UploadPlugin";
// compose headers data
var sheader = "";
sheader += "--" + boundary + "\r\nContent-disposition: form-data; name=\"";
sheader += uploadFormName +"\"\r\n\r\n";
sheader += "backupDir="+uploadParams[3] +
";user=" + uploadParams[4] +
";password=" + uploadParams[5] +
";uploaddir=" + uploadParams[2];
if (bidix.debugMode)
sheader += ";debug=1";
sheader += ";;\r\n";
sheader += "\r\n" + "--" + boundary + "\r\n";
sheader += "Content-disposition: form-data; name=\"userfile\"; filename=\""+uploadParams[1]+"\"\r\n";
sheader += "Content-Type: text/html;charset=UTF-8" + "\r\n";
sheader += "Content-Length: " + data.length + "\r\n\r\n";
// compose trailer data
var strailer = new String();
strailer = "\r\n--" + boundary + "--\r\n";
data = sheader + data + strailer;
if (bidix.debugMode) alert("about to execute Http - POST on "+uploadParams[0]+"\n with \n"+data.substr(0,500)+ " ... ");
var r = doHttp("POST",uploadParams[0],data,"multipart/form-data; ;charset=UTF-8; boundary="+boundary,uploadParams[4],uploadParams[5],localCallback,params,null);
if (typeof r == "string")
displayMessage(r);
return r;
};
// same as Saving's updateOriginal but without convertUnicodeToUTF8 calls
bidix.upload.updateOriginal = function(original, posDiv)
{
if (!posDiv)
posDiv = locateStoreArea(original);
if((posDiv[0] == -1) || (posDiv[1] == -1)) {
alert(config.messages.invalidFileError.format([localPath]));
return;
}
var revised = original.substr(0,posDiv[0] + startSaveArea.length) + "\n" +
store.allTiddlersAsHtml() + "\n" +
original.substr(posDiv[1]);
var newSiteTitle = getPageTitle().htmlEncode();
revised = revised.replaceChunk("<title"+">","</title"+">"," " + newSiteTitle + " ");
revised = updateMarkupBlock(revised,"PRE-HEAD","MarkupPreHead");
revised = updateMarkupBlock(revised,"POST-HEAD","MarkupPostHead");
revised = updateMarkupBlock(revised,"PRE-BODY","MarkupPreBody");
revised = updateMarkupBlock(revised,"POST-SCRIPT","MarkupPostBody");
return revised;
};
//
// UploadLog
//
// config.options.chkUploadLog :
// false : no logging
// true : logging
// config.options.txtUploadLogMaxLine :
// -1 : no limit
// 0 : no Log lines but UploadLog is still in place
// n : the last n lines are only kept
// NaN : no limit (-1)
bidix.UploadLog = function() {
if (!config.options.chkUploadLog)
return; // this.tiddler = null
this.tiddler = store.getTiddler("UploadLog");
if (!this.tiddler) {
this.tiddler = new Tiddler();
this.tiddler.title = "UploadLog";
this.tiddler.text = "| !date | !user | !location | !storeUrl | !uploadDir | !toFilename | !backupdir | !origin |";
this.tiddler.created = new Date();
this.tiddler.modifier = config.options.txtUserName;
this.tiddler.modified = new Date();
store.addTiddler(this.tiddler);
}
return this;
};
bidix.UploadLog.prototype.addText = function(text) {
if (!this.tiddler)
return;
// retrieve maxLine when we need it
var maxLine = parseInt(config.options.txtUploadLogMaxLine,10);
if (isNaN(maxLine))
maxLine = -1;
// add text
if (maxLine != 0)
this.tiddler.text = this.tiddler.text + text;
// Trunck to maxLine
if (maxLine >= 0) {
var textArray = this.tiddler.text.split('\n');
if (textArray.length > maxLine + 1)
textArray.splice(1,textArray.length-1-maxLine);
this.tiddler.text = textArray.join('\n');
}
// update tiddler fields
this.tiddler.modifier = config.options.txtUserName;
this.tiddler.modified = new Date();
store.addTiddler(this.tiddler);
// refresh and notifiy for immediate update
story.refreshTiddler(this.tiddler.title);
store.notify(this.tiddler.title, true);
};
bidix.UploadLog.prototype.startUpload = function(storeUrl, toFilename, uploadDir, backupDir) {
if (!this.tiddler)
return;
var now = new Date();
var text = "\n| ";
var filename = bidix.basename(document.location.toString());
if (!filename) filename = '/';
text += now.formatString("0DD/0MM/YYYY 0hh:0mm:0ss") +" | ";
text += config.options.txtUserName + " | ";
text += "[["+filename+"|"+location + "]] |";
text += " [[" + bidix.basename(storeUrl) + "|" + storeUrl + "]] | ";
text += uploadDir + " | ";
text += "[[" + bidix.basename(toFilename) + " | " +toFilename + "]] | ";
text += backupDir + " |";
this.addText(text);
};
bidix.UploadLog.prototype.endUpload = function(status) {
if (!this.tiddler)
return;
this.addText(" "+status+" |");
};
//
// Utilities
//
bidix.checkPlugin = function(plugin, major, minor, revision) {
var ext = version.extensions[plugin];
if (!
(ext &&
((ext.major > major) ||
((ext.major == major) && (ext.minor > minor)) ||
((ext.major == major) && (ext.minor == minor) && (ext.revision >= revision))))) {
// write error in PluginManager
if (pluginInfo)
pluginInfo.log.push("Requires " + plugin + " " + major + "." + minor + "." + revision);
eval(plugin); // generate an error : "Error: ReferenceError: xxxx is not defined"
}
};
bidix.dirname = function(filePath) {
if (!filePath)
return;
var lastpos;
if ((lastpos = filePath.lastIndexOf("/")) != -1) {
return filePath.substring(0, lastpos);
} else {
return filePath.substring(0, filePath.lastIndexOf("\\"));
}
};
bidix.basename = function(filePath) {
if (!filePath)
return;
var lastpos;
if ((lastpos = filePath.lastIndexOf("#")) != -1)
filePath = filePath.substring(0, lastpos);
if ((lastpos = filePath.lastIndexOf("/")) != -1) {
return filePath.substring(lastpos + 1);
} else
return filePath.substring(filePath.lastIndexOf("\\")+1);
};
bidix.initOption = function(name,value) {
if (!config.options[name])
config.options[name] = value;
};
//
// Initializations
//
// require PasswordOptionPlugin 1.0.1 or better
bidix.checkPlugin("PasswordOptionPlugin", 1, 0, 1);
// styleSheet
setStylesheet('.txtUploadStoreUrl, .txtUploadBackupDir, .txtUploadDir {width: 22em;}',"uploadPluginStyles");
//optionsDesc
merge(config.optionsDesc,{
txtUploadStoreUrl: "Url of the UploadService script (default: store.php)",
txtUploadFilename: "Filename of the uploaded file (default: in index.html)",
txtUploadDir: "Relative Directory where to store the file (default: . (downloadService directory))",
txtUploadBackupDir: "Relative Directory where to backup the file. If empty no backup. (default: ''(empty))",
txtUploadUserName: "Upload Username",
pasUploadPassword: "Upload Password",
chkUploadLog: "do Logging in UploadLog (default: true)",
txtUploadLogMaxLine: "Maximum of lines in UploadLog (default: 10)"
});
// Options Initializations
bidix.initOption('txtUploadStoreUrl','');
bidix.initOption('txtUploadFilename','');
bidix.initOption('txtUploadDir','');
bidix.initOption('txtUploadBackupDir','');
bidix.initOption('txtUploadUserName','');
bidix.initOption('pasUploadPassword','');
bidix.initOption('chkUploadLog',true);
bidix.initOption('txtUploadLogMaxLine','10');
// Backstage
merge(config.tasks,{
uploadOptions: {text: "upload", tooltip: "Change UploadOptions and Upload", content: '<<uploadOptions>>'}
});
config.backstageTasks.push("uploadOptions");
//}}}
/***
|''Name:''|Jon Robson's VismoLibrary|
|''Description:''|An opensource library of javascript code designed to create clickable graphics in canvas with VML alternative for Internet Explorer browsers. The purpose of this is to provide hackable, extendable graphics based plugins without being locked in to consumer products such as Flash.|
|''Author:''|JonRobson (http://www.jonrobson.me.uk/Vismo)|
|''CodeRepository:''|http://svn.tiddlywiki.org/Trunk/contributors/JonRobson/Library/Vismo/|
|''Version:''|0.9 |
|''Dependencies:''| Requires jQuery|
|''Comments:''|Please raise questions and make comments at http://groups.google.co.uk/group/TiddlyWikiDev |
|''License:''|[[BSD License|http://www.opensource.org/licenses/bsd-license.php]] |
|''Usage:''|
Not much good on it's own - it provides some nice functions to create graphicsy plugins.
Currently provides horsepower to the following plugins amongst others:
GeoTiddlyWiki (http://www.jonrobson.me.uk/workspaces/tiddlers/GeoTiddlyWiki/), ImageTaggingPlugin, TiddlyTagMindMap (http://tiddlytagmindmap.tiddlyspot.com)
!Wouldn't have been possible without..
http://spatialreference.org/ref/sr-org/google-projection/ for help with google projection hack
***/
var VismoOptimisations = {
minradius:5,
packCoordinates: function(coordlist){
var res = [];
for(var i=0; i < coordlist.length-1; i+=2){
res.push([coordlist[i],coordlist[i+1]]);
}
return res;
}
,unpackCoordinates: function(coordlist){
var res = [];
for(var i=0; i < coordlist.length; i+=1){
res.push(coordlist[i][0]);
res.push(coordlist[i][1]);
}
return res;
}
//coords in form [[x1,y1],[x2,y2]]
,douglasPeucker: function(coords,tolerance, start,end){
var results = [];
if(!start) start = 0;
if(!end) end = coords.length - 1;
if(start >= coords.length || end >= coords.length || start == end -1){
return [];
}
var midpoint = {};
midpoint.x = (coords[end][0] + coords[start][0]) /2;
midpoint.y = (coords[end][1] + coords[start][1]) /2;
var bestPoint = {distance:-1, index:-1};
for(var i=start+1; i < end; i++){
var x = coords[i][0];
var y = coords[i][1];
var deltax = midpoint.x - x;
var deltay= midpoint.y - y;
var perpendicular_d = Math.sqrt((deltax * deltax ) + (deltay *deltay)); //this is not perpendicular distancd.. i think!
if(perpendicular_d > bestPoint.distance){
bestPoint.index = i;
bestPoint.distance = perpendicular_d;
}
}
if(bestPoint.index ==-1 || bestPoint.distance<tolerance){
var res = [];
res.push(coords[start]);
//res.push(coords[end])
return res; //none of these points are interesting except last
}
else{
results.push(coords[start]);
var ref = bestPoint.index;
var splice1 = VismoOptimisations.douglasPeucker(coords,tolerance,start+1,ref);
var splice2 = VismoOptimisations.douglasPeucker(coords,tolerance,ref,end);
results = results.concat(splice1);
results = results.concat(splice2);
results.push(coords[end]);
return results;
}
}
,vismoShapeIsInVisibleArea: function(vismoShape,canvas,transformation){
var t1= new Date();
var left = 0,top = 0;
var right = parseInt(canvas.width) + left;
var bottom = parseInt(canvas.height) + top;
var topleft = VismoClickingUtils.undotransformation(left,top,transformation);
var bottomright = VismoClickingUtils.undotransformation(right,bottom,transformation);
var frame = {};
frame.top = topleft.y;
frame.bottom = bottomright.y;
frame.right = bottomright.x;
frame.left = topleft.x;
var g = vismoShape.getBoundingBox();
var t2 = new Date();
VismoTimer["shape_visiblearea"] += (t2-t1);
if(g.x2 < frame.left) {
return false;}
if(g.y2 < frame.top) {
return false;}
if(g.x1 > frame.right){
return false;
}
if(g.y1 > frame.bottom){
return false;
}
return true;
}
,vismoShapeIsTooSmall: function(vismoShape,transformation){
VismoTimer.start("VismoOptimisations.vismoShapeIsTooSmall");
if(!transformation ||!transformation.scale) {
VismoTimer.end("VismoOptimisations.vismoShapeIsTooSmall");
return false;
}
var g = vismoShape.getBoundingBox();
var s = transformation.scale;
var t1 = (g.width) * s.x;
var t2 =(g.height) * s.y;
if(t2 < this.minradius&& t1 < this.minradius)
{
VismoTimer.end("VismoOptimisations.vismoShapeIsTooSmall");
return true;}//too small
else{
VismoTimer.end("VismoOptimisations.vismoShapeIsTooSmall");
return false;
}
VismoTimer.end("VismoOptimisations.vismoShapeIsTooSmall");
}
};window.onbeforeunload =function(){
try{
VismoUtils.scrubNodes(window.documentElement);
if (window.CollectGarbage) {
window.CollectGarbage();
}
}
catch(e){
//get over it
}
};
Array.prototype.contains = function(item)
{
return this.indexOf(item) != -1;
};
Array.prototype.clone = function () {var a = new Array(); for (var property in this) {a[property] = typeof (this[property]) == 'object' ? this[property].clone() : this[property]} return a};
if(!Array.indexOf) {
Array.prototype.indexOf = function(item,from)
{
if(!from)
from = 0;
for(var i=from; i<this.length; i++) {
if(this[i] === item)
return i;
}
return -1;
};
}
var VismoShapeUtils ={
randomColor: function(alpha){
var r = parseInt(Math.random() * 255);
var g = parseInt(Math.random() * 255);
var b = parseInt(Math.random() * 255);
var a;
if(alpha) var a = parseInt(Math.random() * 255);
else a = 1;
return "rgba("+r+","+g+","+b+","+a+")";
}
,_isCoordinate: function(c){
if(c == "M" || c == "q" || c== 'c') return false;
else {
if(typeof(c)== 'number') return true;
}
}
,toHex: function(rgba){
if(rgba.indexOf("rgba") == 0){
rgba = rgba.replace("rgba(","");
rgba = rgba.replace(")","");
}
else if(rgba.indexOf("rgb")==0){
rgba = rgba.replace("rgb(","");
}
rgba = rgba.replace(")","");
rgba = rgba.split(",");
return "#"+this._tohexadecimal(rgba[0])+this._tohexadecimal(rgba[1]) +this._tohexadecimal(rgba[2]);
}
,_tohexadecimal: function(N){
if (N==null) return "00";
N=parseInt(N); if (N==0 || isNaN(N)) return "00";
N=Math.max(0,N); N=Math.min(N,255); N=Math.round(N);
return "0123456789ABCDEF".charAt((N-N%16)/16)
+ "0123456789ABCDEF".charAt(N%16);
}
,opacityFrom: function(rgba){
var rgbcode = rgba.replace("rgba(","");
rgbcode = rgbcode.replace(")","");
rgbcode = rgbcode.split(",");
var opvalue = 0;
if(rgbcode.length < 4) opvalue = 1;
else opvalue =rgbcode[3];
return opvalue;
}
,toRgb: function(hex_rgba,opacity){
var rgb = {};
if(hex_rgba.indexOf("#") == 0 && hex_rgba.indexOf(",") == -1){ //hex code argument
var hex = hex_rgba;
var hexcode = hex.substring(1);
rgb.red = this._hexToR(hexcode);
rgb.blue = this._hexToB(hexcode);
rgb.green = this._hexToG(hexcode);
}
else if(hex_rgba.indexOf("rgba") != -1){
var rgbcode = hex_rgba.replace("rgba(","");
rgbcode = rgbcode.replace(")","");
rgbcode = rgbcode.split(",");
rgb.red =rgbcode[0];
rgb.green =rgbcode[1];
rgb.blue =rgbcode[2];
opacity = rgbcode[3];
}
return {rgb:"rgb("+rgb.red+","+ rgb.green +","+ rgb.blue+")",opacity:opacity};
}
,toRgba: function(hex,opacity){
var rgb = {};
if(hex.indexOf("#") == 0 && hex.indexOf(",") == -1){ //hex code argument
var hexcode = hex.substring(1);
rgb.red = this._hexToR(hexcode);
rgb.blue = this._hexToB(hexcode);
rgb.green = this._hexToG(hexcode);
}
if(!opacity) opacity = "1.0";
return "rgba("+rgb.red+","+ rgb.green +","+ rgb.blue+"," + opacity+")";
}
/* thank you http://www.javascripter.net/faq/hextorgb.htm*/
,_cutHex: function(h) {return (h.charAt(0)=="#") ? h.substring(1,7):h}
,_hexToR:function(h){return parseInt((this._cutHex(h)).substring(0,2),16)}
,_hexToG: function (h) {return parseInt((this._cutHex(h)).substring(2,4),16)}
,_hexToB:function(h) {return parseInt((this._cutHex(h)).substring(4,6),16)}
};
var VismoUtils = {
userAgent: navigator.userAgent.toLowerCase(),
clone: function(obj){
if(!obj) return obj;
if(obj.appendChild) return obj;
if(obj == null || typeof(obj) != 'object')return obj;
var temp = new obj.constructor(); // changed (twice)
for(var key in obj){
//console.log(key);
temp[key] = VismoUtils.clone(obj[key]);
//console.log(temp[key])
}
return temp;
}
,invertYCoordinates: function(coords){
var res = [];
for(var i=0; i < coords.length; i++){
var x = coords[i][0];
var y = coords[i][1];
res.push([x,-y]);
}
return res;
},
scrubNode: function(e)
{
if(!VismoUtils.browser.isIE)
return;
var att = e.attributes;
if(att) {
for(var t=0; t<att.length; t++) {
var n = att[t].name;
if(n !== "style" && (typeof e[n] === "function" || (typeof e[n] === "object" && e[n] != null))) {
try {
e[n] = null;
} catch(ex) {
}
}
}
}
var c = e.firstChild;
while(c) {
VismoUtils.scrubNode(c);
c = c.nextSibling;
}
}
,mergejsons: function(prop1,prop2){
var res = {};
var i;
for(i in prop1){
res[i] = prop1[i];
}
for(i in prop2){
res[i] = prop1[i];
}
return res;
}
};
VismoUtils.browser= {
isIE: VismoUtils.userAgent.indexOf("msie") != -1 && VismoUtils.userAgent.indexOf("opera") == -1,
isGecko: VismoUtils.userAgent.indexOf("gecko") != -1,
ieVersion: /MSIE (\d.\d)/i.exec(VismoUtils.userAgent), // config.browser.ieVersion[1], if it exists, will be the IE version string, eg "6.0"
isSafari: VismoUtils.userAgent.indexOf("applewebkit") != -1,
isBadSafari: !((new RegExp("[\u0150\u0170]","g")).test("\u0150")),
firefoxDate: /gecko\/(\d{8})/i.exec(VismoUtils.userAgent), // config.browser.firefoxDate[1], if it exists, will be Firefox release date as "YYYYMMDD"
isOpera: VismoUtils.userAgent.indexOf("opera") != -1,
isLinux: VismoUtils.userAgent.indexOf("linux") != -1,
isUnix: VismoUtils.userAgent.indexOf("x11") != -1,
isMac: VismoUtils.userAgent.indexOf("mac") != -1,
isWindows: VismoUtils.userAgent.indexOf("win") != -1
};
if(VismoUtils.browser.isIE && VismoUtils.browser.ieVersion[1] == "6.0"){
VismoUtils.browser.isIE6 = true;
}
if(VismoUtils.browser.isIE){
if (!document.namespaces['vismoShapeVml_']) {
document.namespaces.add('vismoShapeVml_', 'urn:schemas-microsoft-com:vml'/*,"#default#VML"*/);
}
document.namespaces.add('xmlns', 'http://www.w3.org/1999/xhtml');
document.namespaces.add('svg', 'http://www.w3.org/2000/svg');
document.namespaces.add('xlink', 'http://www.w3.org/1999/xlink');
// Setup default CSS. Only add one style sheet per document
if (!document.styleSheets['vismoShape']) {
var ss = document.createStyleSheet();
ss.owningElement.id = 'vismoShape';
ss.cssText = 'canvas{display:inline;overflow:hidden;' +
'text-align:left;}' +
'vismoShapeVml_\\: * {behavior:url(#default#VML);}';
}
}
VismoUtils.svgSupport = function(){
if(VismoUtils.browser.isIE){
try {
var asv = new ActiveXObject("Adobe.SVGCtl");
return true;
}
catch(e){ }
}
else if(document.implementation) {
if(VismoUtils.browser.isSafari) return true;
return document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Shape", "1.0");
}
return true;
};
/*
Creates primitive shapes that can be rendered across most browsers
I am not very happy with the code that follows. It is not of the best standard and needs much improvement
coordinates are a string consisting of floats and move commands (M)
*/
var VismoShape = function(properties,coordinates){
this._isVismoShape = true;
this.options = {pointsize:5};
if(!coordinates) {
coordinates = properties.coordinates;
delete properties["coordinates"];
}
this._optimise_cache = {};
this.coordinates = {
projected: false,
normal: [],
optimised: {},
optimisedandprojected:{}
};
this.grid = {};
this.width = 0;
this.height =0;
this.properties = {};
this.setProperties(properties);
if(coordinates[0] && coordinates[0].length == 2){
coordinates = VismoOptimisations.unpackCoordinates(coordinates);
}
this._construct(properties,coordinates);
this.browser =false;
this.currentResolution = false;
this.vml = false;
this.unique_id = Math.random() + "_" + this.properties.id;
this.scale = {x:1,y:1};
};
VismoShape.prototype={
isCommand: function(i){
if(i == 'M' || i =='b'){
return true;
}
else{
return false;
}
}
,clone: function(){
var coords = this.getCoordinates("normal");
var props = this.getProperties();
var p = VismoUtils.clone(props);
p.coordinates = coords;
try{
//console.log(p);
return new VismoShape(p);
}
catch(e){
throw e;
}
}
,translate: function(x,y){
var c = this.getCoordinates("normal");
var newc = [];
for(var i=0; i < c.length; i+=2){
if(this.isCommand(c[i])) i+=1;
var newx,newy;
newx = c[i] + x;
newy = c[i+1] + y;
newc.push(newx);
newc.push(newy);
}
this.setCoordinates(newc);
}
,scale: function(x,y){
this._scale.x = x;
this._scale.y = y;
var c = this.getCoordinates("normal");
var newc = [];
for(var i=0; i < c.length; i+=2){
if(this.isCommand(c[i])) i+=1;
var newx,newy;
newx = c[i] * x;
newy = c[i+1] * y;
newc.push(newx);
newc.push(newy);
}
this.setCoordinates(newc);
return true;
}
,resize: function(x,y){
var bb = this.getBoundingBox();
var newWidth = x *bb.width;
var newHeight = y * bb.height;
var offsetx = (bb.center.x * x) - bb.center.x;
var offsety = (bb.center.y * y)- bb.center.y;
this.scale.x = x;
this.scale.y = y;
var c = this.getCoordinates("normal");
var newc = [];
for(var i=0; i < c.length; i+=2){
var newx,newy;
newx = c[i] * x;
newy = c[i+1] * y;
newx -= offsetx;
newy -= offsety;
newc.push(newx);
newc.push(newy);
}
this.setCoordinates(newc);
return true;
}
,moveTo: function(x,y){
var st = this.properties.shape;
var dim = this.getDimensions();
if(st == "point" || st == 'circle'){
this.setCoordinates([x,y,dim.width/2, dim.height/2]);
}
else if(st == 'polygon' ||st == 'path'){
var bb = this.getBoundingBox();
var movex = x - bb.center.x;
var movey = y - bb.center.y;
var c = this.getCoordinates("normal");
var newc = [];
for(var i=0; i < c.length; i+=2){
if(this.isCommand(c[i])) i +=1;
newc.push(c[i]+movex);
newc.push(c[i+1]+movey);
}
this.setCoordinates(newc);
}
}
,getShape: function(){
return this.getProperty("shape");
}
,setProperties: function(properties){
var newprops = VismoUtils.clone(properties);
var i;
for(i in newprops){
this.setProperty(i,newprops[i]);
}
if(!newprops["z-index"]){
this.setProperty("z-index","0");
}
if(!newprops.stroke){
this.setProperty("stroke",'#000000');
}
}
,getBoundingBox: function(){ /* returns untransformed bounding box */
return this.grid;
}
,setPointSize: function(pointsize){
VismoTimer.start("VismoShape.setPointSize");
var st = this.properties.shape;
if(st != "point") return;
if(pointsize) {
this.options.pointsize = pointsize;
var bb= this.getBoundingBox();
this.setCoordinates([bb.center.x,bb.center.y,pointsize/2,pointsize/2]);
}
VismoTimer.end("VismoShape.setPointSize");
}
,render: function(canvas,transformation,projection,optimisations, browser,pointsize){
VismoTimer.start("VismoShape.render");
this.setPointSize(pointsize);
var mode = this.getRenderMode(canvas);
if(mode == 'ie'){
this.render_ie(canvas,transformation,projection,optimisations, browser);
}
else{
this.render_canvas(canvas,transformation,projection,optimisations, browser);
//this.render = this.render_canvas;
}
VismoTimer.end("VismoShape.render");
}
,render_ie: function(canvas,transformation,projection,optimisations, browser){
VismoTimer.start("VismoShape.render_ie");
if(this.properties.hidden){
if(this.vml)this.vml.clear();
return;
}
if(this.vml===false){ //not created
this.vml = new VismoVector(this,canvas);
this.donevml = true;
}
this.vml.render(canvas,transformation,projection);
VismoTimer.end("VismoShape.render_ie");
return;
}
,render_canvas: function(canvas,transformation,projection,optimisations, browser){
VismoTimer.start("VismoShape.render_canvas");
var c;
if(this.properties.hidden) {
return;
}
var vismoShape = this;
var ctx = canvas.getContext('2d');
if(!ctx) return;
ctx.save();
if(transformation){
var o = transformation.origin;
var tr = transformation.translate;
var s = transformation.scale;
var r = transformation.rotate;
if(o && s && tr){
ctx.translate(o.x,o.y);
ctx.scale(s.x,s.y);
ctx.translate(tr.x,tr.y);
}
if(r && r.x)ctx.rotate(r.x);
}
VismoCanvasRenderer.renderShape(canvas,vismoShape);
ctx.restore();
VismoTimer.end("VismoShape.render_canvas");
}
,getTransformation: function(){
var transform= this.getProperty("transformation");
if(!transform) transform = {translate:false,scale:false};
if(!transform.translate)transform.translate = {x:0,y:0};
if(!transform.translate.x)transform.translate.x = 0;
if(!transform.translate.y)transform.translate.y = 0;
if(!transform.scale)transform.scale= {x:1,y:1};
if(!transform.scale.x)transform.scale.x = 1;
if(!transform.scale.y)transform.scale.y = 1;
return transform;
}
,setTransformation: function(transformation){
this.setProperty("transformation",transformation);
this._calculateBounds();
}
,setCoordinates: function(coordinates,type){
if(this.properties.shape == 'circle' || this.properties.shape == 'point'){
if(coordinates.length == 2 && this.coordinates.normal){
coordinates.push(this.coordinates.normal[2]);
coordinates.push(this.coordinates.normal[3]);
}
}
var good = [];
for(var i=0; i < coordinates.length; i++){
if(coordinates[i] +"" !='NaN')
{good.push(coordinates[i]);}
}
if(good.length < 2) {
throw "cannot set coordinates for VismoShape not enough good coordinates given (coordinates may contain non-number elements)" + coordinates.toString();
}
coordinates = good;
if(type == 'projected'){
this.coordinates.projected = coordinates;return;}
this.coordinates.normal = coordinates;
if(this.vml)this.vml.coordinatesHaveChanged();
this.coordinates.projected= false;
var i;
for(i in this.coordinates_optimised){
delete this.coordinates_optimised[i];
}
var j;
for(j in this.coordinates.optimisedandprojected){
delete this.coordinates.optimisedandprojected[j];
}
this.grid = {}; //an enclosing grid
if(this.vml) this.vml.path = false; //reset path so recalculation will occur
var st = this.getShape();
if(st== 'circle' || st == 'point'){
if(coordinates[2] && coordinates[3]) this.setRadius(coordinates[2],coordinates[3]);
else this.setDimensions(this.options.pointsize,this.options.pointsize);
}
this._calculateBounds();
}
,getCoordinates: function(type){
if(type == 'normal') return this.coordinates.normal;
if(type == 'projected') return this.coordinates.projected;
var resolution = this.currentResolution;
if(this.coordinates.projected) {
if(this.browser != 'ie' && resolution){
return this._simplifyCoordinates(resolution,this.coordinates.projected);
var opt=this.coordinates.optimisedandprojected;
if(!opt[resolution]) opt[resolution] = this._simplifyCoordinates(resolution,this.coordinates.projected);
return opt[resolution];
}
return this.coordinates.projected;
}
else{
if(this.browser != 'ie' && resolution){
var opt=this.coordinates.optimised;
if(!opt[resolution]) opt[resolution] = this._simplifyCoordinates(resolution,this.coordinates.normal);
return opt[resolution];
}
return this.coordinates.normal;
}
}
,getProperties: function(){
return this.properties;
}
,getRenderMode: function(canvas){
VismoTimer.start("VismoShape.getRenderMode");
if(!this.browser){
if(!canvas.getContext) {
this.browser = "ie";
}
else this.browser = "good";
}
VismoTimer.end("VismoShape.getRenderMode");
return this.browser;
}
,setProperty: function(name,value){
this.properties[name] = value;
//console.log("Reset",name,this);
if(this.vml) {
this.vml.nochange = false;
}
if(name == 'z-index'){ //organise a re-sort for the z-index property to kick in
if(Vismo.store.Canvas[this._canvasref]){
Vismo.store.Canvas[this._canvasref].needsSort = true;
}
}
}
,getProperty: function(name){
return this.properties[name];
}
,_calculateBounds: function(coords){
VismoTimer.start("VismoShapes._calculateBounds");
var that = this;
var st = this.getShape();
var transform = this.getTransformation();
if(st == 'path'){
this.grid = {x1:0,x2:1,y1:0,y2:1,center:{x:0,y:0}};
return;
}
else if(st == 'point' || st == 'circle' | st == 'image' | st == 'domElement'){
var coords = this.getCoordinates("normal").clone();
var x = coords[0]; var y = coords[1];
var dim = this.getDimensions();
this.grid.center = {};
this.grid.center.x = x;
this.grid.center.y = y;
if(transform){
if(transform.translate){
var tran_x = transform.translate.x;
var tran_y = transform.translate.y;
this.grid.center.x += tran_x;
this.grid.center.y += tran_y;
}
if(transform.scale){
dim.width *= transform.scale.x;
dim.height *= transform.scale.y;
}
}
var newx = this.grid.center.x;
var newy = this.grid.center.y;
var radiusw = dim.width / 2;
var radiush = dim.height / 2;
this.grid ={x1: newx -radiusw ,x2: newx + radiusw, y1: newy - radiush, y2: newy + radiush,center:{x:newx,y:newy},width: dim.width,height:dim.height};
//console.log(this.grid.center.x,this.coordinates.normal,this.properties.transformation);
return;
}
if(!coords) coords = this.getCoordinates();
if(coords.length < 2) return;
this.grid.x1 = coords[0];
this.grid.y1 = coords[1];
this.grid.x2 = coords[0];
this.grid.y2 = coords[1];
this._deltas = []
var d = this._deltas;
var lastX, lastY;
var index = 0;
lastX = coords[0];
lastY = coords[1];
for(var i=0; i < coords.length-1; i+=2){
var xPos = parseFloat(coords[i]); //long
var yPos = parseFloat(coords[i+1]); //lat
var deltax =xPos - lastX;
var deltay= yPos - lastY;
if(deltax < 0) deltax = - deltax;
if(deltay < 0) deltay = -deltay;
d.push(deltax);
d.push(deltay);
if(xPos < this.grid.x1) this.grid.x1 = xPos;
if(yPos < this.grid.y1) this.grid.y1 = yPos;
if(xPos > this.grid.x2) this.grid.x2 = xPos;
if(yPos > this.grid.y2) this.grid.y2 = yPos;
lastX = xPos;
lastY = yPos;
}
//this.grid.x2 *= transform.scale.x;
//this.grid.y2 *= transform.scale.y;
this.grid.width = (this.grid.x2 - this.grid.x1);
this.grid.height = (this.grid.y2 - this.grid.y1);
/*var transform = this.getTransformation();
if(transform && transform.scale){
var scale = transform.scale;
this.grid.width *= scale.x;
this.grid.height *= scale.y;
}*/
this.grid.center = {};
this.grid.center.x = (this.grid.x2 - this.grid.x1) / 2 + this.grid.x1;
this.grid.center.y = (this.grid.y2 - this.grid.y1) / 2 + this.grid.y1;
//recalculate based on scaling
this.grid.width *= transform.scale.x;
this.grid.height *= transform.scale.y;
this.grid.center.x += transform.translate.x;
this.grid.center.y += transform.translate.y;
var halfw = this.grid.width / 2;
var halfh = this.grid.height /2;
this.grid.x1 = this.grid.center.x - halfw;
this.grid.x2 = this.grid.center.x + halfw;
this.grid.y1 = this.grid.center.y - halfh;
this.grid.y2 = this.grid.center.y + halfh;
/* if(transform && transform.translate){
var trans = transform.translate;
this.grid.center.x += trans.x;
this.grid.center.y += trans.y;
}
*/
this.grid.x1 = this.grid.center.x - (this.grid.width / 2);
this.grid.x2 = this.grid.center.x + (this.grid.width /2);
this.grid.y1 = this.grid.center.y - (this.grid.height/2);
this.grid.y2 = this.grid.center.y +(this.grid.height/2);
VismoTimer.end("VismoShapes._calculateBounds");
//if(st == 'path') console.log(this,this.grid);
}
,getCanvas: function(){
return this.vismoCanvas;
}
,setRadius: function(rx,ry){
if(!ry) ry = rx;
this.setDimensions(rx*2,ry*2);
}
,getRadius: function(){
if(this.width) return this.width /2;
else{
var bb = this.getBoundingBox();
return bb.width / 2;
}
}
,setDimensions: function(width,height){
this.width = width;
this.height = height;
if(this.properties.shape == 'point'){
this.options.pointsize = width;
}
this._calculateBounds();
}
,getDimensions: function(){
return {width: this.width, height: this.height};
}
,_construct: function(properties, coordinates){
VismoTimer.start("VismoShapes._construct");
var shapetype =properties.shape;
if(!shapetype) shapetype = 'polygon';
if(shapetype == 'point' || shapetype == 'circle'){
var radiusw,radiush;
if(coordinates[2]) radiusw = coordinates[2];
else radiusw = this.options.pointsize/2;
if(coordinates[3]) radiush= coordinates[3];
else radiush = radiusw;
this.setDimensions(radiusw*2,radiush*2);
this.setCoordinates([coordinates[0],coordinates[1],radiusw,radiush]);
}
else if(shapetype == 'polygon' || shapetype == 'path')
{
this.setCoordinates(coordinates);
}
else if(shapetype == 'domElement'){
var w = jQuery(this.getProperty("element")).width();
var h = jQuery(this.getProperty("element")).height();
this.setDimensions(w,h);
this.setCoordinates(coordinates);
}
else if(shapetype == 'image'){
var src = this.getProperty("src");
if(!src) throw "all images must carry a property src at minimum";
var image = new Image();
image.src= src;
this.image = image;
var vismoShape = this;
var w = vismoShape.getProperty("width"); h= vismoShape.getProperty("height");
if(coordinates.length > 2){
w = coordinates[2]; h = coordinates[3];
}
image.onload = function(){
if(!w && !h){
vismoShape.setDimensions(w,h);
vismoShape.setCoordinates([coordinates[0],coordinates[1]]);
}
vismoShape.ready = true;
};
if(image.complete)vismoShape.ready = true;
vismoShape.setDimensions(w,h);
vismoShape.setCoordinates([coordinates[0],coordinates[1]]);
}
else{
console.log("don't know how to construct basic shape " + properties.shape);
}
VismoTimer.end("VismoShapes._construct");
}
,_applyProjection: function(projection,transformation){
VismoTimer.start("VismoShapes._applyProjection");
var c = this.getCoordinates('normal');
if(!projection || !projection.xy) return c;
if(projection.init) projection.init();
var newc = [];
for(var i=0; i < c.length-1; i+=2){
var moved = false;
if(!VismoShapeUtils._isCoordinate(c[i])){
i+= 1;
}
var x = parseFloat(c[i]);
var y = parseFloat(c[i+1]);
var newx,newy;
var projectedCoordinate = projection.xy(c[i],c[i+1],transformation);
if(projectedCoordinate.x && projectedCoordinate.y){
newx= projectedCoordinate.x;
newy= projectedCoordinate.y;
if(projectedCoordinate.move){
moved =true;
}
cok = true;
//check we haven't wrapped around world (For flat projections sss)
if(!projection.nowrap){
var diff;
if(newx > x) diff = newx - x;
if(x > newx) diff = x - newx;
if(diff > 100) cok = false; //too extreme change
}
if(cok){
if(VismoShapeUtils._isCoordinate(x) && VismoShapeUtils._isCoordinate(y)){
if(moved){
newc.push("M");
}
newc.push(newx);
newc.push(newy);
}
}
}
}
if(newc.length < 2) return;
this.setCoordinates(newc,"projected");
this._calculateBounds(newc);
VismoTimer.end("VismoShapes._applyProjection");
return newc;
}
,optimise: function(canvas,transformation,projection,justcompute){
VismoTimer.start("VismoShapes.optimise");
var ocache = this._optimise_cache;
var cid = transformation["cache"]["id1"];
var cid2 =transformation["cache"]["id2"];
if(this.scale.x > 1){
var newx,newy;
newx = this.scale.x * transformation.scale.x;
newy = this.scale.y * transformation.scale.y;
cid = newx + ","+newy;
}
if(!ocache[cid]) ocache[cid] = {};
if(typeof(ocache[cid][cid2]) != "undefined"){
return ocache[cid][cid2];
}
var shapetype = this.properties.shape;
if(shapetype == "path") {
ocache[cid][cid2] = true;
VismoTimer.end("VismoShapes.optimise");
return true;
}
if(transformation && transformation.scale) {
this.currentResolution = Math.min(transformation.scale.x, transformation.scale.y);
}
if(projection) {this._applyProjection(projection,transformation);}
if(shapetype != 'point' && shapetype != 'path' && shapetype !="domElement"){ //check if worth drawing
if(VismoOptimisations.vismoShapeIsTooSmall(this,transformation)) {
if(!justcompute && this.vml)this.vml.clear();
ocache[cid][cid2] = false;
VismoTimer.end("VismoShapes.optimise");
return false;
}
}
if(!VismoOptimisations.vismoShapeIsInVisibleArea(this,canvas,transformation)){
if(!justcompute && this.vml)this.vml.clear();
ocache[cid][cid2] = false;
VismoTimer.end("VismoShapes.optimise");
return false;
}
ocache[cid][cid2] = true;
VismoTimer.end("VismoShapes.optimise");
return true;
}
,optimise_ie: function(canvas,transformation,projection){
VismoTimer.start("VismoShape.optimise_ie");
var ocache = this._optimise_cache;
var cid = transformation["cache"]["id1"];
if(typeof(ocache[cid]) != "undefined"){
return ocache[cid];
}
VismoOptimisations.minradius = 6;
var sh = this.properties.shape;
if(sh == 'path' || sh == 'point') {
ocache[cid] =true;
return true;
}
if(VismoOptimisations.vismoShapeIsTooSmall(this,transformation)) {
if(this.vml)this.vml.clear();
VismoTimer.end("VismoShape.optimise_ie");
ocache[cid] =false;
return false;
}
ocache[cid] =true;
VismoTimer.end("VismoShape.optimise_ie");
return true;
}
,_simplifyCoordinates: function(scaleFactor,coordinates){// **
VismoTimer.start("VismoShapes._simplifyCoordinates");
if(this.getProperty("shape") == 'path') return coordinates;
/*will use http://www.jarno.demon.nl/polygon.htm#ref2 */
if(!coordinates) throw "give me some coordinates!";
var originals =coordinates;
var tolerance;
var bb = this.getBoundingBox();
var d;
if(bb.width < bb.height) d = bb.width;
else d = bb.height;
tolerance = (d/4) / scaleFactor;
coordinates = VismoOptimisations.packCoordinates(coordinates);
coordinates = VismoOptimisations.douglasPeucker(coordinates,tolerance);
coordinates = VismoOptimisations.unpackCoordinates(coordinates);
var diff = originals.length - coordinates.length;
VismoTimer.end("VismoShapes._simplifyCoordinates");
if(diff < 10) return originals;
else
return coordinates;
}
};/*
A package for rendering geojson polygon and point features easily to create maps
*/
var GeoTag = function(longitude,latitude,properties){
var geo = {};
geo.type = "feature";
geo.geometry = {};
geo.geometry.type = "point";
geo.geometry.coordinates = [longitude,latitude];
geo.properties = properties;
return geo;
};
var VismoMap = function(wrapper,options){
if(wrapper.length){ //for jquery
var result = [];
for(var i=0; i < wrapper.length; i++){
var x = new VismoMap(wrapper[i],options);
result.push(x);
}
return x;
}
if(typeof wrapper == 'string') wrapper = document.getElementById(wrapper);
else wrapper = wrapper;
this.wrapper = wrapper;
wrapper.vismoMap = this;
//wrapper.style.position = "relative";
var that = this;
this.settings = {};
var w= jQuery(wrapper).width();
var h= jQuery(wrapper).height();
jQuery(wrapper).css({width:w,height:h});
this.feature_reference = {};
if(!options) options = {};
var that = this;
var handler = function(t){
that.transform(t);
}
//if(!options.vismoController) options.vismoController = {};
if(options.vismoController)options.vismoController.handler = handler;
this.vismoCanvas = new VismoCanvas(wrapper,options);
this.controller = this.vismoCanvas.vismoController;
//run stuff
if(this.controller)this.transform(this.controller.transformation); //set initial transformation
this._fittocanvas = true;
this.geofeatures = {};
this.features = [];
this.clear();
var proj = options.projection;
var eMap = this;
this._hijackMouseFunctions();
if(options.tooltip){
this.vismoCanvas.addTooltip(function(el,s){
if(s){
el.innerHTML = s.getProperty("name");
}
});
}
this.mouse({down:options.mousedown,up:options.mouseup,move:options.move,dblclick:options.dblclick,keypress:options.keypress});
var eMap = this;
if(proj){
if(proj == 'globe' || proj == 'spinnyglobe'){
eMap = new VismoGlobe(this);
if(proj == 'spinnyglobe'){
eMap.toggleSpin();
}
}
if(proj == 'google'){
eMap.settings.projection = VismoSlippyMap.prototype.getGoogleMercatorProjection();
}
else if(proj == 'slippystaticmap'){
eMap = new VismoSlippyMap(this);
}
}
if(options.geojson){
this.drawFromGeojson(options.geojson,options.fullscreen);
}
else if(options.georss){
this.drawFromGeojson(VismoConversion.geoRssToGeoJson(options.georss),options.fullscreen);
}
else if(options.kml){
this.drawFromGeojson(VismoConversion.kmlToGeoJson(options.kml),options.fullscreen);
}
return eMap;
};
VismoMap.prototype = {
setTransparency: function(args){
var alpha = arguments[0];
this.vismoCanvas.setTransparency(alpha);
}
,getVismoShapes: function(args){
return this.vismoCanvas.getMemory();
}
,resize: function(args){
var width = arguments[0];
var height = arguments[1];
this.wrapper.style.width = width+"px";
this.wrapper.style.height = height +"px";
var t=this.getTransformation();
t.origin.x = width / 2;
t.origin.y = height / 2;
this.setTransformation(t);
this.vismoCanvas.resize(width,height);
this.clear();
}
,getProjection: function(args){
return this.settings.projection;
}
,setProjection: function(args){
var projection = arguments[0];
this.settings.projection = projection;
}
,clear: function(args){ /* does this work in IE? */
var deleteMemory = arguments[0];
this.vismoCanvas.clear(deleteMemory);
},
drawFromGeojson: function(args){
var geojson = arguments[0];
var autosize = arguments[1];
if(typeof geojson == 'string'){
geojson = eval('(' +geojson+ ')');
}
this._lastgeojson = geojson;
if(autosize){
var t = VismoMapUtils.fitgeojsontocanvas(geojson,this.wrapper);
var p =this.getProjection();
if(p && p.name == "GLOBE") {
t.translate = {x:0,y:0};
}
this.controller.setTransformation(t);
}
var type =geojson.type.toLowerCase();
if(type == "featurecollection"){
var features = geojson.features;
this.drawGeoJsonFeatures(features);
} else if(type =='feature') {
this.drawGeoJsonFeature(geojson);
} else {
console.log("only feature collections currently supported");
}
this.render();
},
drawFromGeojsonFile: function(args){
var file = arguments[0];
var that = this;
var callback = function(status,params,responseText,url,xhr){
that.drawFromGeojson(responseText);
};
VismoFileUtils.loadRemoteFile(file,callback);
}
,getTransformation: function(args){
if(!this.transformation){
return false;
}
else
return this.transformation;
}
,setTransformation: function(args){
var transformation = arguments[0];
if(typeof transformation.translate.x != 'number'||typeof transformation.translate.y != 'number') throw "bad transformation translate given ";
if(typeof transformation.scale.x != 'number'||typeof transformation.scale.y != 'number') throw "bad transformation scale given ";
this.controller.setTransformation(transformation);
}
,moveTo: function(args){
var longitude= arguments[0];
var latitude = arguments[1];
var zoom = arguments[2];
var newt = {translate:{},scale:{}};
var transformation =this.getTransformation();
var newxy={};
newxy.x = parseFloat(longitude);
newxy.y = parseFloat(latitude);
if(this.settings.projection){
newxy = this.settings.projection.xy(newxy.x,newxy.y,transformation);
}
newt.translate.x = - newxy.x;
newt.translate.y = newxy.y;
if(!zoom){
zoom =transformation.scale.x;
}
else{
zoom = parseFloat(zoom);
}
newt.scale.x = zoom;
newt.scale.y = zoom;
this.controller.setTransformation(newt)
}
,redraw: function(args){
this.render();
//alert("average VML render"+ VismoVector.rstats);
//alert("total average VML render time"+ VismoVector.rstats * VismoVector.rnum);
},
transform: function(args){
var transformation = arguments[0];
//console.log(arguments);
var w =parseInt(this.wrapper.style.width);
var h = parseInt(this.wrapper.style.height);
var t =transformation.translate;
var s = transformation.scale;
this.transformation = transformation;
/*if(!transformation.origin){
this.transformation.origin = {};
var origin = this.transformation.origin;
origin.x =w / 2;
origin.y =h / 2;
}*/
if(s.x < 0.5) s.x = 0.5;
if(s.y < 0.5) s.y = 0.5;
if(t.x > 180) t.x = 180; //t.x=Math.min(t.x, 180)
if(t.x < -180) t.x = -180;
if(t.y > 85.0511) t.y = 85.0511;
if(t.y < -85.0511) t.y = -85.0511;
if(!this.transformation.rotate){
this.transformation.rotate = {x:0,y:0,z:0};
}
var that = this;
var f = function(args){
that.vismoCanvas.setTransformation(that.transformation);
that.redraw();
}
window.setTimeout(f,0);
},
/*onmouseup and ove are functions with following parameters:
e,shape,mouse,longitude_latitude,feature
*/
mouse: function(args){
if(!args){
return {up: this.onmouseup, down: this.onmousedown, move: this.onmousemove, dblclick: this.ondblclick,keypress:this.onkeypress};
}
if(args.move)this.onmousemove =args.move;
if(args.up)this.onmouseup = args.up;
if(args.down)this.onmouseup = args.down;
if(args.keypress) this.onkeypress = args.keypress;
if(args.dblclick) this.ondblClick = args.dblclick;
}
,_hijackMouseFunctions: function(args){
var eMap = this;
var getParameters = function(e){
var result = {};
var code;
if (e.which) code =e.which;
else if (e.keyCode) code = e.keyCode;
var character;
if(code) character = String.fromCharCode(code);
var t = VismoClickingUtils.resolveTargetWithVismo(e);
if(t && t.getAttribute("class") == 'vismoControl') return false;
var shape = eMap.vismoCanvas.getShapeAtClick(e);
if(shape) {
result.shape = shape;
result.feature = eMap.geofeatures[eMap.vismoCanvas.getMemoryID(shape)];
}
var pos = VismoClickingUtils.getMouseFromEvent(e);
var x =pos.x;
var y = pos.y;
result.mouse = pos;
result.longitude_latitude = VismoMapUtils.getLongLatFromMouse(x,y,eMap);
result.event = e;
result.keypressed = character;
return result;
};
var md = function(e,s){
var r = getParameters(e);
if(eMap.onmousedown) eMap.onmousedown(e,s,r.mouse,r.longitude_latitude,r.feature,r.key,eMap);
};
var mu = function(e,s){
var r = getParameters(e);
if(eMap.onmouseup) eMap.onmouseup(e,s,r.mouse,r.longitude_latitude,r.feature,r.key,eMap);
};
var mm = function(e,s){
var r = getParameters(e);
if(eMap.onmousemove) eMap.onmousemove(e,s,r.mouse,r.longitude_latitude,r.feature,r.key,eMap);
};
var dbl = function(e,s){
var r = getParameters(e);
if(eMap.ondblClick) eMap.ondblClick(e,s,r.mouse,r.longitude_latitude,r.feature,r.key,eMap);
};
var key = function(e,s){
var r = getParameters(e);
if(eMap.onkeypress) eMap.onkeypress(e,s,r.mouse,r.longtitude_latitude,r.feature,r.key,eMap);
}
this.vismoCanvas.mouse({mousedown:md,mouseup:mu,mousemove:mm,dblclick:dbl,keypress:key});
}
,render: function(args){
var d1 = new Date();
var flag = arguments[0];
var tran =this.transformation;
var that = this;
this.vismoCanvas.render(this.settings.projection);
if(this.settings.afterRender) {
this.settings.afterRender(tran);
}
var t = document.getElementById(that.wrapper.id + "_statustext");
if(t) {
t.parentNode.removeChild(t);
}
var d2 = new Date();
var id="mapRender";
if(!VismoTimer[id]) VismoTimer[id] = 0;
VismoTimer[id] += (d2 - d1);
},
getFeatures: function(args){
if(arguments[0] && this.features[arguments[0]]) return this.features[arguments[0]];
return this.features;
}
,drawGeoJsonFeature: function(args){
var featuredata = arguments[0];
var props = arguments[1];
var feature = new VismoMap.Feature(featuredata,props);
var s = feature.getVismoShapes();
for(var i=0; i < s.length; i++){
this.vismoCanvas.add(s[i]);
//this.geofeatures[this.vismoCanvas.getMemoryID(s[i])] = feature;
}
this.features.push(feature);
},
drawGeoJsonFeatures: function(args){
var features = arguments[0];
var avg1 = 0;
for(var i=0; i < features.length; i++){
this.drawGeoJsonFeature(features[i],{featureid:i});
}
}
,getVismoCanvas: function(args){
return this.vismoCanvas;
}
};
VismoMap.Feature = function(feature,props){
this.init(feature,props);
};
VismoMap.Feature.prototype = {
init: function(args){
var feature = arguments[0];
if(arguments[1])extra_properties = arguments[1];
else extra_properties = {};
this.properties = feature.properties;
this.geometry = feature.geometry;
this.outers = [];
this.vismoShapes = [];
var geometry = this.geometry;
var type =geometry.type.toLowerCase();
if(type == 'multipolygon'){
this._drawGeoJsonMultiPolygonFeature(feature.geometry.coordinates,feature);
}
else if(type == 'linestring' || type=='multilinestring' || type == 'multipoint' || type=='geometrycollection'){
console.log(type + " not supported yet");
}
else if(type == 'polygon'){
this._drawGeoJsonPolygonFeature(feature.geometry.coordinates,feature);
}
else if(type == 'point'){
this._drawGeoJsonPointFeature(feature.geometry.coordinates,feature);
}
else {
console.log("unsupported geojson geometry type " + geometry.type);
}
var x = this.getVismoShapes();
var f;
for(f in extra_properties){
for(var i=0; i < x.length; i++){
x[i].setProperty(f,extra_properties[f]);
}
}
}
,addOuterVismoShape: function(args){
var shape = arguments[0];
this.outers.push(shape);
}
,getOuterVismoShapes: function(args){
return this.outers;
}
,addVismoShape: function(args){
var vismoShape = arguments[0];
this.vismoShapes.push(vismoShape);
}
,getVismoShapes: function(args){
return this.vismoShapes;
}
,_drawGeoJsonMultiPolygonFeature: function(args){
var coordinates= arguments[0];
var feature = arguments[1];
var outer;
for(var i=0; i < coordinates.length; i++){ //it's a list of polygons!
var s = this._drawGeoJsonPolygonFeature(coordinates[i],feature,i);
}
},
_drawGeoJsonPolygonFeature: function(args){
var coordinates= arguments[0];
var feature = arguments[1];
var featureid = arguments[2];
var p = feature.properties;
p.shape = 'polygon';
//console.log(coordinates[0]);
var outer = false;
for(var j=0; j< coordinates.length; j++){//identify and create each polygon
var coords =coordinates[j];
coords = VismoUtils.invertYCoordinates(coords);
var s = new VismoShape(p,coords);
s.properties.geometryid = featureid;
s.properties.geometryid2 = j;
this.addVismoShape(s);
}
return outer;
},
_drawGeoJsonPointFeature: function(args){
var coordinates= arguments[0];
var feature = arguments[1];
var p = feature.properties;
p.shape = 'point';
coordinates[1] = -coordinates[1];
var s = new VismoShape(p,coordinates);
this.addVismoShape(s);
}
,setProperty: function(args){
var id = arguments[0];
var val = arguments[1];
var shapes = this.getVismoShapes();
for(var i=0; i < shapes.length;i++){
shapes[i].setProperty(id,val);
}
}
};
/*Extends VismoMaps to provide tiled background */
var VismoGlobe= function(eMap){
var i;
for(i in VismoGlobe.prototype){
eMap[i] = VismoGlobe.prototype[i];
}
eMap.setGlobeProjection("GLOBE");
return eMap;
};
VismoGlobe.prototype = {
setGlobeProjection: function(){
var vismomap = this;
vismomap._fittocanvas = false;
this.settings.beforeRender = function(t){
vismomap._createGlobe(vismomap.getProjection().getRadius(t.scale));
};
this.settings.projection= {
name: "GLOBE",
nowrap:true,
radius: 10,
direction: 0
,init: function(){
this.direction = 0;
}
,getRadius: function(){
return this.radius;
}
,inversexy: function(x,y,t){
var radius =this.getRadius(t.scale);
var res = VismoMapUtils._undospherify(x,y,t,radius);
return res;
}
,xy: function(x,y,t){
var radius =this.getRadius(t.scale);
if(!radius || !x || !y || !t) return {x:x,y:y};
var res = VismoMapUtils._spherifycoordinate(x,y,t,radius);
/*
if(res.movedNorth && this.direction >= 0){
this.direction = -1;
res.move= true;
}
else if(res.movedSouth && this.direction <= 0){
this.direction = 1;
res.move = true;
}
if(res.y > radius - 10 || res.y < 10-radius){
res.y = false;
}*/
return res;
}
};
var heightR = parseInt(vismomap.wrapper.style.height) /2;
var widthR= parseInt(vismomap.wrapper.style.width) /2;
if(widthR > heightR){
this.settings.projection.radius = heightR;
}
else{
this.settings.projection.radius = widthR;
}
}
,toggleSpin: function(){
var eMap = this;
var f = function(){
var t = eMap.controller.transformation;
if(!t.rotate) t.rotate = {};
if(!t.rotate.z) t.rotate.z = 0;
t.rotate.z += 0.3;
eMap.controller.setTransformation(t);
window.setTimeout(f,600);
};
f();
}
,_createGlobe: function(radius){
if(VismoUtils.browser.isIE) {return;}
var ctx = this.vismoClicking.canvas.getContext('2d');
if(!ctx) return;
var t =this.controller.transformation;
var tr =t.translate;
var s = t.scale;
var o = t.origin;
ctx.save();
ctx.translate(o.x,o.y);
ctx.scale(s.x,s.y);
ctx.translate(tr.x,tr.y);
var radgrad = ctx.createRadialGradient(0,0,10,0,0,radius);
radgrad.addColorStop(0,"#AFDCEC");
radgrad.addColorStop(0.5, '#00C9FF');
radgrad.addColorStop(1, '#00B5E2');
radgrad.addColorStop(1, 'rgba(0,201,255,0)');
ctx.beginPath();
ctx.arc(0, 0, radius, 0, Math.PI*2, true);
ctx.closePath();
ctx.fillStyle = radgrad;
ctx.fill();
ctx.restore();
}
};
var VismoSlippyMap = function(vismoMap){
//vismoMap.resize(512,512);
this.loadedurls = {};
this.setupSlippyStaticMapLayer(vismoMap);
vismoMap.oldDrawFromGeojson = vismoMap.drawFromGeojson
vismoMap.drawFromGeojson = function(geojson,autosize){
vismoMap.oldDrawFromGeojson(geojson,false);
};
return vismoMap;
};
VismoSlippyMap.prototype = {
getGoogleMercatorProjection: function(vismomap){
var p = {};
p.source = new Proj4js.Proj('WGS84');//
p.dest = new Proj4js.Proj('GOOGLE');
p.resultCache = {};
var that = this;
p.getTileServerUrl = function(){
return that.tileserverurl;
}
p.tilesize = 256;
p.googleHack = 1/((2 * Math.PI * 6378137) /p.tilesize);
p.inversexy = function(x,y){
x /= this.googleHack;
y /= this.googleHack;
var pointSource = new Proj4js.Point(x ,y);
var pointDest = Proj4js.transform(p.dest,p.source, pointSource);
return pointDest;
}
p.calculatescalefactor= function(vismomapscale,res){
if(!res){
if(vismomapscale <= 1){
return 0;
}
else{
res = 0;
}
}
if(vismomapscale <= 1){
return res;
}
else{
var news = vismomapscale / 2;
res +=1 ;
return this.calculatescalefactor(news,res);
}
};
p.xy = function(x,y,t){
if(this.resultCache[x+"|"+y]) {
return this.resultCache[x+"|"+y];
}
var pointSource = new Proj4js.Point(x,y);
var pointDest = Proj4js.transform(p.source,p.dest, pointSource);
var newx =pointDest.x;
var newy = pointDest.y;
newx *= this.googleHack;
newy *= this.googleHack;
this.resultCache[x+"|"+y] = {x:newx , y:newy};
return this.resultCache[x+"|"+y];
}
return p;
}
,setupSlippyStaticMapLayer: function(eMap){
/*Filename(url) format is /zoom/x/y.png */
var projection = this.getGoogleMercatorProjection(eMap);
//var projection = {};
eMap.setTransparency(0.7);
eMap.settings.projection = projection;
var that = this;
var mapheight =parseInt(eMap.wrapper.style.height);
var mapwidth =parseInt(eMap.wrapper.style.width);
var tileGridDimension = {x:mapwidth/projection.tilesize + 1,y:(mapheight/projection.tilesize) + 1};
var tiles = this._createTiles(eMap,tileGridDimension.x,tileGridDimension.y);
var eMap = eMap;
eMap.settings.afterRender = function(transformation){
var origin = transformation.origin;
jQuery(that.tilesWrapper).css({top: origin.y, left: origin.x});
var zoomOut = false;
if(eMap.settings.lastScale > transformation.scale.x)
zoomOut = true;
eMap.settings.lastScale = transformation.scale.x;
var x =0,y =0,lo,la, translate= transformation.translate,scale= transformation.scale;
eMap.wrapper.style.backgroundImage = "none";
var zoomL = projection.calculatescalefactor(scale.x);
var mapheight =parseInt(eMap.wrapper.style.height);
var mapwidth =parseInt(eMap.wrapper.style.width);
var tile = tiles["main"];
var left = (scale.x * translate.x);
var top = (scale.y * translate.y);
top += (origin.y - 128);
left += (origin.x - 128);
tile.style.top = top + "px";
tile.style.left = left + "px";
if(zoomL == 0){
var i;
for(i in tiles){
tiles[i].style.backgroundImage ="none";
}
zoomL = 0;
tilex = 0;tiley=0;
var slippyurl =projection.getTileServerUrl()+zoomL +"/"+tilex+"/"+tiley+".png";
that.renderTile(slippyurl,zoomL,tilex,tiley,tile);
}
else{
tiles.main.style.backgroundImage = "none";
var temp ={x: (translate.x),y:(translate.y)};
temp.x *= scale.x;
temp.y *= scale.y;
temp.x += (origin.x);
temp.y += (origin.y);
var tlleft = temp.x;
var tltop =temp.y;
//brtop = brtop%(256);
tlleft= temp.x % 256;
tltop = temp.y % 256;
if(tltop > 0) tltop -= 256;
if(tltop < -256) tltop += 256;
if(tlleft < -256) tlleft += 256;
if(tlleft > 0) tlleft -= 256;
var lola;
lola = VismoMapUtils.getLongLatAtXY(tlleft+128,tltop+128,eMap);
var tltilexy =VismoMapUtils.getSlippyTileNumber(lola.longitude,lola.latitude,zoomL,eMap);
for(var idX=0; idX < tileGridDimension.x; idX++){
for(var idY=0; idY < tileGridDimension.y; idY++){
var leftShift = idX;
var upShift = idY;
var index = idX + "|"+idY;
var tile = tiles[index];
var top = tltop + (256 * idY);
var left = tlleft + (256 *idX);
var tilex = tltilexy.x + idX;
var tiley = tltilexy.y + idY;
var numtiles = Math.pow(2,zoomL);
if(tilex < 0) tilex = numtiles + tilex;
if(tiley < 0) tiley = numtiles + tiley;
if(tilex >= numtiles) tilex -= numtiles;
if(tiley >= numtiles) tiley -= numtiles;
tile.style.left = left +"px";
tile.style.top = top + "px";
tile.title = zoomL+"/"+tilex + "/" + tiley;
var slippyurl ="http://tile.openstreetmap.org/"+zoomL +"/"+tilex+"/"+tiley+".png";
that.renderTile(slippyurl,zoomL,tilex,tiley,tile);
}
}
}
};
}
,renderTile: function(weburl,zoomlevel,x,y,tile){
var that = this;
var renderTile = function(dest){
tile.style.backgroundImage = "none";
var style ="url('"+dest+"')";
if(style == tile.style.backgroundImage) return;
tile.style.backgroundImage = style;
//var numtiles = Math.pw(2,zoomL);
};
var renderTileWeb = function(url){
var style ="url('"+url+"')";
tile.style.backgroundImage = "none";
if(style == tile.style.backgroundImage) return;
tile.style.backgroundImage = style;
};
try{
var localurl = zoomlevel+ "_"+ x + "_" + y + ".png";
if(localurl != tile.style.backgroundImage){
if(that.loadedurls[localurl]){
renderTile(localurl);
}
else{
tile.style.backgroundImage = "none";
VismoFileUtils.saveImageLocally(weburl,localurl,renderTile,renderTileWeb);
that.loadedurls[localurl] = true;
}
}
}
catch(e){
tile.style.backgroundImage = "none";
//console.log("unable to cache static image for this map view. ("+e+")")
}
}
,_createTiles: function(eMap,numtilesx,numtilesy){
var res = {};
var tiles = document.createElement("div");
tiles.style.overflow = "hidden";
tiles.className = "VismoTileWrapper"
tiles.style.position= "absolute";
tiles.style.width = eMap.wrapper.style.width;
tiles.style.height = eMap.wrapper.style.height;
var maintile = document.createElement("div");
maintile.style.position = "absolute";
maintile.style.width = "256px";
maintile.style.height = "256px";
tiles.appendChild(maintile);
for(var y = 0; y < numtilesy; y++){
for(var x = 0; x < numtilesx; x++){
var tile = document.createElement("div");
tile.className = "tile_"+x+ "_"+y;
tile.style.position = "absolute";
tile.style.width = "256px";
tile.style.height = "256px";
//if(x == 0 && y == 0) tile.style.border = "solid 1px black";
var index =x+"|"+y;
tiles.appendChild(tile);
res[index] = tile;
}
}
eMap.wrapper.appendChild(tiles);
res['main'] = maintile;
return res;
}
};/*requires VismoShapes
Adds controls such as panning and zooming to a given dom element.
Mousewheel zooming currently not working as should - should center on location where mousewheel occurs
Will be changed to take a handler parameter rather then a targetjs
*/
var VismoController = function(elem,options){ //elem must have style.width and style.height etM
if(elem.length){ //for jquery
var result = [];
for(var i=0; i < elem.length; i++){
var x = new VismoController(elem[i],options);
result.push(x);
}
return x;
}
if(!options)options = {};
if(elem.vismoController) throw "this already has a vismo controller!"
elem.vismoController = true;// this;
this.enabledControls = [];
if(typeof elem == 'string') elem= document.getElementById(elem);
this.setLimits({});
//jQuery(elem).css()
//if(!elem.style || !elem.style.position) elem.style.position = "relative";
this.wrapper = elem; //a dom element to detect mouse actions
this.handler = options.handler; //a js object to run actions on (with pan and zoom functions)
this.defaultCursor = "";
var md = elem.onmousedown;
var mu = elem.onmouseup;
var mm = elem.onmousemove;
for(var i=0; i < elem.childNodes.length; i++){
var child = elem.childNodes[i];
try{
child.onmousedown = function(e){if(md)md(e);}
child.onmouseup = function(e){if(mu)mu(e);}
child.onmousemove = function(e){if(mm)mm(e);}
}
catch(e){
}
}
controlDiv = document.createElement('div');
controlDiv.style.position = "absolute";
controlDiv.style.top = "0";
controlDiv.style.left = "0";
controlDiv.className = 'vismoControls';
jQuery(controlDiv).css({'z-index':10000, height:"120px",width:"60px"});
this.wrapper.appendChild(controlDiv);
this.controlDiv = controlDiv;
this.controlCanvas = new VismoCanvas(this.controlDiv);
//this.controlDiv.vismoController = this;
var vismoController = this;
var preventDef = function(e){
if (e && e.stopPropagation) //if stopPropagation method supported
e.stopPropagation()
else
e.cancelBubble=true
return false;
};
var that = this;
var f = function(e,s){
var vismoController = that;
vismoController._panzoomClickHandler(e,s,vismoController);
return preventDef(e);
};
this.controlCanvas.mouse({up:preventDef,down:f,dblclick:preventDef});
//this.wrapper.vismoController = this;
this.transformation = {'translate':{x:0,y:0}, 'scale': {x:1, y:1},'rotate': {x:0,y:0,z:0},origin:{}};
this.transformation.origin.x = jQuery(elem).width() / 2;
this.transformation.origin.y = jQuery(elem).height() / 2;
var t = this.transformation;
//looks for specifically named function in targetjs
if(!this.handler) {
alert("no transform handler function defined");
}
//this.wrapper.vismoController = this;
this.enabled = true;
if(!options) options = {};
if(!options.controls)options.controls =['pan','zoom','mousepanning','mousewheelzooming'];
this.options = options;
this.addControls(this.options.controls);
this.limits = {scale:{}};
if(this.options.maxZoom) {
this.limits.scale.x =this.options.maxZoom;
this.limits.scale.y = this.options.maxZoom;
}
if(this.options.minZoom){
this.limits.scale.minx =this.options.minZoom;
this.limits.scale.miny =this.options.minZoom;
}
this.pansensitivity =100;
if(this.options.pansensitivity){
this.pansensitivity =this.options.pansensitivity;
}
};
VismoController.prototype = {
setLimits: function(transformation){
this.limits = transformation;
}
,getHandler: function(){
return this.handler;
}
,setHandler: function(handler){
this.handler = handler;
handler(this.transformation);
}
,getEnabledControls: function(){
return this.enabledControls;
}
,_addEnabledControl: function(controlName){
this.enabledControls.push(controlName);
}
,applyLayer: function(){
var that = this;
var hidebuttons = function(){
var shapes = that.controlCanvas.getMemory();
for(var i=0; i < shapes.length; i++){
shapes[i].setProperty("hidden",true);
}
that.controlCanvas.render();
};
this.controlCanvas.render();
if(this.options.hidebuttons){
hidebuttons();
return;
}
if(VismoUtils.browser.isIE6) return;
var enabled = this.getEnabledControls();
var pan,zoom;
if(enabled.contains("pan")) pan = true;
if(enabled.contains("zoom")) zoom = true;
var callback = function(response){
if(!response)return;
if(!VismoUtils.svgSupport())return;
var shape;
if(false == true){
//return;
shape = document.createElement("div");
shape.innerHTML = response;
}
else{
shape = document.createElement('object');
shape.setAttribute('codebase', 'http://www.adobe.com/svg/viewer/install/');
if(VismoUtils.browser.isIE)shape.setAttribute('classid', '15');
shape.setAttribute('style',"overflow:hidden;position:absolute;z-index:0;width:60px;height:120px;");
shape.setAttribute('type',"image/svg+xml");
var dataString = 'data:image/svg+xml,'+ response;
shape.setAttribute('data', dataString); // the "<svg>...</svg>" returned from Ajax call
jQuery(shape).css({width:60,height:120})
}
that.controlDiv.appendChild(shape);
jQuery(that.controlDiv).css({"background-image":"none"});
hidebuttons();
};
if(pan && zoom) callback(this.panzoomcontrolsSVG);
}
,getTransformation: function(){
return this.transformation;
}
,translate: function(x,y){
var t= this.getTransformation();
t.translate.x = x;
t.translate.y = y;
this.transform();
},
addMouseWheelZooming: function(){ /*not supported for internet explorer*/
var that = this;
this._addEnabledControl("mousewheelzooming");
this.crosshair = {lastdelta:false};
this.crosshair.pos = {x:0,y:0};
var t = this.getTransformation();
var mw = this.wrapper.onmousewheel;
var that = this;
var mm = this.wrapper.onmousemove;
var doingmw = false;
var mwactive = false;
var cancelMouseZoomCursor = function(){
if(VismoUtils.browser.isIE6)that.wrapper.style.cursor = "";
else jQuery(that.wrapper).removeClass("zooming");
}
jQuery(this.wrapper).mousedown(function(e){
mwactive = true;
if(VismoUtils.browser.isIE6)this.style.cursor = "crosshair";
else {
if(!jQuery(that.wrapper).hasClass("panning")){
jQuery(that.wrapper).addClass("zooming");
}
}
window.setTimeout(cancelMouseZoomCursor,2000);
});
jQuery(this.wrapper).mouseout(function(e){
var newTarget;
if(e.toElement) newTarget = e.toElement;
else newTarget = e.relatedTarget;
if(jQuery(newTarget,that.wrapper).length == 0){ //if not a child turn off
mwactive = false;
}
cancelMouseZoomCursor();
});
var domw = function(e){
if(!that.enabled) return;
/* thanks to http://adomas.org/javascript-mouse-wheel */
var delta = 0;
if(!that.goodToTransform(e)) {
doingmw = false;
return false;
}
var t = VismoClickingUtils.resolveTargetWithVismo(e);
t= el;
if(t != that.wrapper && t.parentNode !=that.wrapper) return false;
if (e.wheelDelta) { /* IE/Opera. */
delta = e.wheelDelta/120;
/** In Opera 9, delta differs in sign as compared to IE.
*/
if (window.opera)
delta = -delta;
} else if (e.detail) { /** Mozilla case. */
/** In Mozilla, sign of delta is different than in IE.
* Also, delta is multiple of 3.
*/
delta = -e.detail/3;
}
var sensitivity = 0.4;
var transform = that.getTransformation();
var scale =transform.scale;
var origin = transform.origin;
var mousepos = VismoClickingUtils.getMouseFromEvent(e);
var w = parseInt(that.wrapper.style.width) / 2;
var h = parseInt(that.wrapper.style.height) / 2;
var translation = VismoTransformations.undoTransformation(mousepos.x,mousepos.y,that.transformation);
transform.translate= {x: -translation.x, y: -translation.y};
//{x: -mousepos.x + w,y: -mousepos.y + h};
transform.origin = {
x: mousepos.x,
y: mousepos.y
};
if(delta > that.crosshair.lastdelta + sensitivity || delta < that.crosshair.lastdelta - sensitivity){
var newx,newy;
if(delta > 0){
newx = parseFloat(scale.x) * 2;
newy = parseFloat(scale.y) * 2;
}
else{
newx = parseFloat(scale.x) / 2;
newy = parseFloat(scale.y) / 2;
}
if(newx > 0 && newy > 0){
scale.x = newx;
scale.y = newy;
that.setTransformation(transform);
}
}
that.crosshair.lastdelta = delta;
doingmw = false;
return false;
};
var onmousewheel = function(e){
if(!VismoUtils.browser.isIE){
jQuery(that.wrapper).addClass("zooming");
}
if(e.preventDefault){e.preventDefault();}
if (e && e.stopPropagation) {
e.stopPropagation();
}
e.cancelBubble=true;
if(!mwactive) return false;
if(!doingmw) {
var f = function(){
domw(e);
return false;
};
window.setTimeout(f,50);
doingmw = true;
}
return false;
};
var element = this.wrapper;
if(VismoUtils.browser.isIE) {
document.onmousewheel = function(e){
if(!e)e = window.event;
var el = e.target;
//var el = e.srcElement;
if(!el) return;
while(el != element){
if(el == element) {
onmousewheel(e);
return false;
}
el = el.parentNode;
}
return;
};
window.onmousewheel = document.onmousewheel;
return;
}
else if (element.addEventListener){
element.onmousewheel = onmousewheel; //safari
element.addEventListener('DOMMouseScroll', onmousewheel, false);/** DOMMouseScroll is for mozilla. */
}
else if(element.attachEvent){
element.attachEvent("onmousewheel", onmousewheel); //safari
}
else{ //it's ie.. or something non-standardised. do nowt
//window.onmousewheel = document.onmousewheel = onmousewheel;
}
}
,disable: function(){
jQuery(".vismoControls",this.wrapper).css({display:"none"});
this.enabled = false;
}
,enable: function(){
this.enabled = true;
jQuery(".vismoControls",this.wrapper).css({display:""});
}
,goodToTransform: function(e){
var t = VismoClickingUtils.resolveTarget(e);
switch(t.tagName){
case "INPUT":
return false;
case "SELECT":
return false;
case "OPTION":
return false;
}
if(t && t.getAttribute("class") == "vismoControl") return false;
return true;
}
,addMousePanning: function(){
this._addEnabledControl("mousepanning");
var that = this;
var el = that.wrapper;
var md = el.onmousedown;
var mu = el.onmouseup;
var mm = el.onmousemove;
var panning_status = false;
//alert('here');
//jQuery(document).mouseup(function(e){alert("cool");}); //doesn't work?!
var cancelPanning = function(e){
panning_status = false;
that.transform();
if(!VismoUtils.browser.isIE6){jQuery(that.wrapper).removeClass("panning");}
//style.cursor= that.defaultCursor;
that.wrapper.onmousemove = mm;
return false;
};
jQuery(that.controlDiv).mousedown(function(e){
cancelPanning();
});
var onmousemove = function(e){
if(e && e.shiftKey) {return false;}
if(mm){mm(e);}
if(!that.enabled) {return;}
if(!panning_status) {
return;
}
if(!VismoUtils.browser.isIE && !jQuery(that.wrapper).hasClass("panning")){
jQuery(that.wrapper).addClass("panning")
}
if(!that.goodToTransform(e)) {return;}
var pos = VismoClickingUtils.getMouseFromEventRelativeToElement(e,panning_status.clickpos.x,panning_status.clickpos.y,panning_status.elem);
if(!pos){return;}
var t = that.getTransformation();
//if(this.transformation) t = this.transformation;
var sc = t.scale;
/* work out deltas */
var xd =parseFloat(pos.x /sc.x);
var yd = parseFloat(pos.y / sc.y);
t.translate.x = panning_status.translate.x + xd;
t.translate.y =panning_status.translate.y +yd;
if(!VismoUtils.browser.isIE6){
jQuery(that.wrapper).removeClass("zooming");
that.transform();
}
that.transform();
if(pos.x > 5 || pos.y > 5) panning_status.isClick = false;
if(pos.x < 5|| pos.y < 5) panning_status.isClick = false;
return false;
};
jQuery(this.wrapper).mousedown(function(e){
var jqw = jQuery(that.wrapper);
if(panning_status){
return;
}
if(md) {md(e);}
if(!that.enabled) return;
if(!VismoUtils.browser.isIE6){
jqw.addClass("panning");
}
var target = VismoClickingUtils.resolveTarget(e);
target = el;
if(!target) return;
var t = that.transformation.translate;
var sc =that.transformation.scale;
var realpos = VismoClickingUtils.getMouseFromEvent(e);
if(!realpos) return;
//this.vismoController = that;
var element = VismoClickingUtils.resolveTargetWithVismo(e);
element = el;
panning_status = {clickpos: realpos, translate:{x: t.x,y:t.y},elem: element,isClick:true};
that.wrapper.onmousemove = onmousemove;
});
jQuery(document).mouseup(function(e){
if(panning_status.isClick && mu){
mu(e);
};
if(panning_status){
cancelPanning(e);
}
});
jQuery(document).mousemove(function(e){
if(panning_status){
onmousemove(e);
var parent= e.target;
while(parent.parentNode){
parent = parent.parentNode;
if(parent == that.wrapper) return;
}
//if(parent != that.wrapper)cancelPanning(e); (not a good idea for tooltips)
}
});
},
setTransformation: function(t){
if(this.limits){
if(this.limits.scale){
if(t.scale.x > this.limits.scale.x){ t.scale.x = this.limits.scale.x;}
if(t.scale.y > this.limits.scale.y){ t.scale.y = this.limits.scale.y; }
if(t.scale.x < this.limits.scale.minx){ t.scale.x = this.limits.scale.minx;}
if(t.scale.y < this.limits.scale.miny){ t.scale.y = this.limits.scale.miny;}
}
}
if(!t.origin){
var w = jQuery(this.wrapper).width();
var h = jQuery(this.wrapper).height();
t.origin = {x: w/2, y: h/2};
}
if(this.enabled){
if(!t.scale && !t.translate && !t.rotate) alert("bad transformation applied - any call to setTransformation must contain translate,scale and rotate");
this.transformation = t;
this.handler(t);
}
//console.log("transformation set to ",t);
},
createButtonLabel: function(r,type,offset){
var properties= {'shape':'path', stroke: '#000000',lineWidth: '1'};
properties.actiontype = type;
var coords=[];
if(type == 'E'){
coords =[r,0,-r,0,'M',r,0,0,-r,"M",r,0,0,r];
}
else if(type =='W'){
coords =[-r,0,r,0,'M',-r,0,0,r,"M",-r,0,0,-r];
}
else if(type == 'S'){
coords =[0,-r,0,r,'M',0,r,-r,0,"M",0,r,r,0];
}
else if(type == 'N'){
coords =[0,-r,0,r,'M',0,-r,r,0,"M",0,-r,-r,0];
}
else if(type == 'in'){
coords =[-r,0,r,0,"M",0,-r,0,r];
}
else if(type == 'out'){
coords = [-r,0,r,0];
}
for(var i=0; i < coords.length; i+=2 ){
if(coords[i] == "M") i+=1;
coords[i] += offset.x;
coords[i+1] += offset.y;
}
return new VismoShape(properties,coords);
},
createButton: function(width,direction,offset,properties) {
var canvas = this.controlCanvas;
if(!canvas) throw "no canvas to create on..";
if(!width) width = 100;
var r = width/2;
offset = {
x: offset.x || 0,
y: offset.y || 0
};
var coords = [
offset.x, offset.y,
offset.x + width, offset.y,
offset.x + width, offset.y + width,
offset.x, offset.y + width
];
properties.shape = 'polygon';
properties.fill ='rgba(150,150,150,0.7)';
var button = new VismoShape(properties,coords);
var bb = button.getBoundingBox();
buttoncenter = {x:bb.center.x,y:bb.center.y};
var label = this.createButtonLabel(r,properties.actiontype,buttoncenter);
canvas.add(label);
canvas.add(button);
return button;
},
addControls: function(list){
for(var i= 0; i < list.length; i++){
this.addControl(list[i]);
}
}
,addControl: function(controlType) {
switch(controlType) {
//case "zoom":
case "pan":
this.addPanningActions();
break;
case "zoom":
this.addZoomingActions();
break;
case "mousepanning":
this.addMousePanning();
break;
case "mousewheelzooming":
this.addMouseWheelZooming();
break;
case "rotation":
this.addRotatingActions();
break;
default:
break;
}
},
addPanningActions: function(controlDiv){
this._addEnabledControl("pan");
this.createButton(10,180,{x:-6,y:-54},{'actiontype':'N','name':'pan north','buttonType': 'narrow'});
this.createButton(10,270,{x:10,y:-38},{'actiontype':'E','name':'pan east','buttonType': 'earrow'});
//this.createButton(10,90,{x:16,y:16},{'actiontype':'O','name':'re-center','buttonType': ''});
this.createButton(10,90,{x:-22,y:-38},{'actiontype':'W','name':'pan west','buttonType': 'warrow'});
this.createButton(10,0,{x:-6,y:-20},{'actiontype':'S','name':'pan south','buttonType': 'sarrow'});
this.applyLayer();
},
addRotatingActions: function(){
/*
var rotateCanvas = this.controlCanvas.getDomElement();
this.createButton(rotateCanvas,10,180,{x:16,y:2},{'actiontype':'rotatezup','name':'pan north','buttonType': 'narrow'});
this.createButton(rotateCanvas,10,0,{x:16,y:30},{'actiontype':'rotatezdown','name':'pan south','buttonType': 'sarrow'});
this.createButton(rotateCanvas,10,270,{x:30,y:16},{'actiontype':'rotatezright','name':'rotate to right','buttonType': 'earrow'});
this.createButton(rotateCanvas,10,90,{x:2,y:16},{'actiontype':'rotatezleft','name':'rotate to left','buttonType': 'warrow'});
rotateCanvas.onmouseup = this._panzoomClickHandler;*/
},
addZoomingActions: function(){
this._addEnabledControl("zoom");
this.createButton(10,180,{x:-6,y:12},{'actiontype':'in','name':'zoom in','buttonType': 'plus'});
this.createButton(10,180,{x:-6,y:42},{'actiontype':'out','name':'zoom out','buttonType': 'minus'});
this.applyLayer();
}
,zoom: function(x,y){
var t = this.getTransformation();
t.scale.x = x;
if(!y) y= x;
t.scale.y = y;
this.setTransformation(t);
}
,panTo: function(x,y){
//if(!this.enabled) return;
var t = this.getTransformation();
var finalX = -x;
var finalY = -y;
var thisx,thisy;
var direction = {};
var difference = {};
thisx = t.translate.x;
thisy = t.translate.y;
difference.x= thisx - finalX;
difference.y = thisy - finalY;
direction.x = -difference.x / 5;
direction.y = -difference.y / 5;
var change = true;
var that = this;
var f = function(){
change= {x: false,y:false};
if(thisx > finalX && thisx + direction.x > finalX) {thisx += direction.x;change.x=true;}
else if(thisx < finalX && thisx + direction.x < finalX) {thisx += direction.x;change.x=true;}
else{
t.translate.x = finalX;
}
if(thisy > finalY && thisy + direction.y > finalY) {thisy += direction.y;change.y=true;}
else if(thisy < finalY && thisy + direction.y < finalY) {thisy += direction.y;change.y=true;}
else{
change.x = true;
t.translate.y =finalY;
}
if(change.x){
t.translate.x = thisx;
}
else{
t.translate.x = finalX;
}
if(change.y){
t.translate.y = thisy;
}
else{
t.translate.y = finalY;
}
if(t.translate.x != finalX && t.translate.y != finalY){
that.setTransformation(t);
window.setTimeout(f,5);
}
else{
that.setTransformation(t);
}
};
f();
//window.setTimeout(pan,200);
}
,transform: function(){
if(this.enabled){
var t = this.getTransformation();
var s = t.scale;
var tr = t.translate;
if(s.x <= 0) s.x = 0.1125;
if(s.y <= 0) s.y = 0.1125;
var ok = true;
var lim = this.limits;
if(lim.scale){
if(s.y < lim.scale.miny) t.scale.y = lim.scale.miny;
if(s.x < lim.scale.minx) t.scale.x = lim.scale.minx;
if(s.y > lim.scale.y) t.scale.y = lim.scale.y;
if(s.x > lim.scale.x) t.scale.x = lim.scale.x;
}
//remove origin?
//var translatex = t.origin.x+ (t.translate.x * t.scale.x);
//var translatey = t.origin.y+ (t.translate.y *t.scale.y);
this.handler(this.transformation);
}
},
_panzoomClickHandler: function(e,hit,controller) {
if(!hit) return;
var pan = {};
var t =controller.getTransformation();
if(!t.scale) t.scale = {x:1,y:1};
if(!t.translate) t.translate = {x:0,y:0};
if(!t.rotate) t.rotate = {x:0,y:0,z:0};
var scale =t.scale;
pan.x = parseFloat(this.pansensitivity / scale.x);
pan.y = parseFloat(this.pansensitivity / scale.y);
switch(hit.getProperty("actiontype")) {
case "W":
t.translate.x += pan.x;
break;
case "O":
t.translate.x = 0;
t.translate.y = 0;
break;
case "E":
t.translate.x -= pan.x;
break;
case "N":
t.translate.y += pan.y;
break;
case "S":
t.translate.y -= pan.y;
break;
case "in":
scale.x *= 2;
scale.y *= 2;
break;
case "out":
scale.x /= 2;
scale.y /= 2;
break;
case "rotatezright":
if(!t.rotate.z) t.rotate.z = 0;
//console.log("right",t.rotate.z);
t.rotate.z -= 0.1;
var left =6.28318531;
if(t.rotate.z <0 )t.rotate.z =left;
break;
case "rotatezup":
if(!t.rotate.y) t.rotate.y = 0;
t.rotate.y += 0.1;
break;
case "rotatezdown":
if(!t.rotate.y) t.rotate.y = 0;
t.rotate.y -= 0.1;
break;
case "rotatezleft":
if(!t.rotate.z) t.rotate.z = 0;
t.rotate.z += 0.1;
break;
default:
break;
}
controller.transform();
//console.log("done",controller);
return false;
}
};
/*VismoController.prototype.panzoomcontrolsSVG ="<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><!-- Created with Inkscape (http://www.inkscape.org/) --><svg xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:cc=\"http://creativecommons.org/ns#\" xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\" xmlns:svg=\"http://www.w3.org/2000/svg\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:sodipodi=\"http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd\" xmlns:inkscape=\"http://www.inkscape.org/namespaces/inkscape\" width=\"60px\" height=\"120px\" id=\"svg3820\" sodipodi:version=\"0.32\" inkscape:version=\"0.46\" sodipodi:docname=\"panzoomcontrols.svg\" inkscape:output_extension=\"org.inkscape.output.svg.inkscape\"> <defs id=\"defs3\"> <linearGradient id=\"linearGradient3735\"> <stop style=\"stop-color:#ffffff;stop-opacity:1;\" offset=\"0\" id=\"stop3737\" /> <stop style=\"stop-color:#0000f0;stop-opacity:1;\" offset=\"1\" id=\"stop3739\" /> </linearGradient> <linearGradient id=\"linearGradient3745\"> <stop style=\"stop-color:#000000;stop-opacity:1;\" offset=\"0\" id=\"stop3747\" /> <stop style=\"stop-color:#ffffef;stop-opacity:0;\" offset=\"1\" id=\"stop3749\" /> </linearGradient> <inkscape:perspective sodipodi:type=\"inkscape:persp3d\" inkscape:vp_x=\"0 : 526.18109 : 1\" inkscape:vp_y=\"6.123234e-14 : 1000 : 0\" inkscape:vp_z=\"744.09448 : 526.18109 : 1\" inkscape:persp3d-origin=\"372.04724 : 350.78739 : 1\" id=\"perspective3826\" /> </defs> <sodipodi:namedview inkscape:document-units=\"mm\" id=\"base\" pagecolor=\"#ffffff\" bordercolor=\"#666666\" borderopacity=\"1.0\" inkscape:pageopacity=\"0.0\" inkscape:pageshadow=\"2\" inkscape:zoom=\"4\" inkscape:cx=\"14.379355\" inkscape:cy=\"60.049799\" inkscape:current-layer=\"layer1\" showgrid=\"true\" inkscape:window-width=\"1440\" inkscape:window-height=\"776\" inkscape:window-x=\"-84\" inkscape:window-y=\"22\" /> <metadata id=\"metadata4\"> <rdf:RDF> <cc:Work rdf:about=\"\"> <dc:format>image/svg+xml</dc:format> <dc:type rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\" /> </cc:Work> </rdf:RDF> </metadata> <g inkscape:label=\"Layer 1\" inkscape:groupmode=\"layer\" id=\"layer1\"> <rect style=\"opacity:1;fill:#fafafa;fill-opacity:1;stroke:#000000;stroke-width:1.25095212000000000;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1\" id=\"rect4374\" width=\"3.036346\" height=\"29.855259\" x=\"26.456741\" y=\"77.110023\" /> <path sodipodi:type=\"arc\" style=\"opacity:0;fill:#ffc100;fill-opacity:0.18999999;fill-rule:evenodd;stroke:#00d300;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.98500001\" id=\"path2811\" sodipodi:cx=\"36.681629\" sodipodi:cy=\"40.457794\" sodipodi:rx=\"22.848825\" sodipodi:ry=\"23.466362\" d=\"M 59.530455,40.457794 A 22.848825,23.466362 0 1 1 13.832804,40.457794 A 22.848825,23.466362 0 1 1 59.530455,40.457794 z\" transform=\"translate(-10.077156,-13.286926)\" /> <path sodipodi:type=\"star\" style=\"fill:#ffffff\" id=\"path2817\" sodipodi:sides=\"5\" sodipodi:cx=\"21.984276\" sodipodi:cy=\"13.286215\" sodipodi:r1=\"0.34933102\" sodipodi:r2=\"0.17466551\" sodipodi:arg1=\"-0.78539816\" sodipodi:arg2=\"-0.15707963\" inkscape:flatsided=\"false\" inkscape:rounded=\"0\" inkscape:randomized=\"0\" d=\"M 22.23129,13.0392 L 22.156791,13.258891 L 22.295532,13.444808 L 22.063572,13.441843 L 21.929628,13.631245 L 21.860769,13.409722 L 21.639246,13.340862 L 21.828648,13.206918 L 21.825683,12.974959 L 22.0116,13.1137 L 22.23129,13.0392 z\" transform=\"translate(-2.9137398,-0.9362086)\" /> <path sodipodi:type=\"arc\" style=\"fill:#fafafa;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.99893030000000005;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;opacity:1\" id=\"path3847\" sodipodi:cx=\"113.64216\" sodipodi:cy=\"108.12209\" sodipodi:rx=\"23.233507\" sodipodi:ry=\"20.960665\" d=\"M 136.87567,108.12209 A 23.233507,20.960665 0 1 1 90.408651,108.12209 A 23.233507,20.960665 0 1 1 136.87567,108.12209 z\" transform=\"matrix(0.9778731,0,0,-1.0598112,-84.661617,141.94941)\" /> <path style=\"fill:#dcdcdc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1\" d=\"M 39.621219,21.031683 L 47.389849,26.975113 L 39.969679,33.117243 L 41.484209,27.164163 L 39.621219,21.031683 z\" id=\"north\" inkscape:label=\"north\" sodipodi:nodetypes=\"ccccc\" /> <path style=\"fill:#dcdcdc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1\" d=\"M 20.231889,13.770245 L 26.175319,6.0016174 L 32.317449,13.421792 L 26.364359,11.907259 L 20.231889,13.770245 z\" id=\"path3757\" inkscape:label=\"north\" sodipodi:nodetypes=\"ccccc\" /> <path style=\"fill:#dcdcdc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1\" d=\"M 20.048989,40.437803 L 25.992419,48.206433 L 32.134549,40.786253 L 26.181459,42.300793 L 20.048989,40.437803 z\" id=\"path3761\" inkscape:label=\"north\" sodipodi:nodetypes=\"ccccc\" /> <path style=\"fill:#dcdcdc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1\" d=\"M 12.629649,33.160653 L 4.8610222,27.217223 L 12.281197,21.075093 L 10.766664,27.028173 L 12.629649,33.160653 z\" id=\"path3765\" inkscape:label=\"north\" sodipodi:nodetypes=\"ccccc\" /> <path sodipodi:type=\"arc\" style=\"fill:#ff0000;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1\" id=\"path3849\" sodipodi:cx=\"114.65231\" sodipodi:cy=\"133.62845\" sodipodi:rx=\"0\" sodipodi:ry=\"2.5253813\" d=\"M 114.65231,133.62845 A 0,2.5253813 0 1 1 114.65231,133.62845 A 0,2.5253813 0 1 1 114.65231,133.62845 z\" /> <path sodipodi:type=\"arc\" style=\"fill:#fafafa;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:3.29227274000000003;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;opacity:1\" id=\"path4600\" sodipodi:cx=\"113.64216\" sodipodi:cy=\"108.12209\" sodipodi:rx=\"23.233507\" sodipodi:ry=\"20.960665\" d=\"M 136.87567,108.12209 A 23.233507,20.960665 0 1 1 90.408651,108.12209 A 23.233507,20.960665 0 1 1 136.87567,108.12209 z\" transform=\"matrix(0.3044572,0,0,-0.3133744,-6.349179,108.99488)\" /> <path sodipodi:type=\"arc\" style=\"fill:#fafafa;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:3.29227274000000003;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;opacity:1\" id=\"path4602\" sodipodi:cx=\"113.64216\" sodipodi:cy=\"108.12209\" sodipodi:rx=\"23.233507\" sodipodi:ry=\"20.960665\" d=\"M 136.87567,108.12209 A 23.233507,20.960665 0 1 1 90.408651,108.12209 A 23.233507,20.960665 0 1 1 136.87567,108.12209 z\" transform=\"matrix(0.3044572,0,0,-0.3133744,-6.5991733,140.49488)\" /> <path style=\"fill:#dcdcdc;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1\" d=\"M 29.344931,79.34136 L 26.693281,79.164583 L 26.870057,76.336156 L 22.804193,76.159379 L 23.157747,73.330952 L 26.870057,73.507729 L 26.870057,70.856078 L 29.875261,71.032855 L 29.875261,73.684505 L 33.587572,74.038059 L 33.587572,76.512933 L 29.521708,76.336156 L 29.344931,79.34136 z\" id=\"path3299\" /> <path style=\"fill:#dcdcdc;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1\" d=\"M 26.781669,107.80241 L 22.715805,107.62563 L 23.069359,104.79721 L 26.781669,104.97398 L 29.786873,105.15076 L 33.499184,105.50431 L 33.499184,107.97919 L 29.43332,107.80241 L 26.781669,107.80241 z\" id=\"path3301\" sodipodi:nodetypes=\"ccccccccc\" /> </g></svg>";*/
/*
Some common utils used throughout package
*/
var VismoMapUtils = {
googlelocalsearchurl: "http://ajax.googleapis.com/ajax/services/search/local?v=1.0&q="
,optimiseForIE6: function(geojson){
var newf = [];
for(var i=0; i < geojson.features.length;i++){
var f = geojson.features[i];
var coordinates = f.geometry.coordinates;
var newc = [];
var good = false;
if(coordinates.length <2){
good = true;
}
for(var j=0; j < coordinates.length; j++){
var c1 = coordinates[j];
}
var bb = f.geometry.bbox;
if(bb){
var dx = bb[2] - bb[0]; var dy= bb[3]- bb[1]; if(dy<0)dy =-dy;if(dx<0)dx =-dx;
if(dx < 1 || dy < 1){
good =false;
}
}
if(good){
newf.push(f);
}
}
geojson.features= newf;
return geojson;
}
,addBoundingBoxes: function(geojson){ //currently MultiPolygon only..
var geojsonbb = geojson;
for(var i=0; i < geojson.features.length; i++){
var f = geojson.features[i];
var g = f.geometry;
var c = g.coordinates;
if(g.type.toLowerCase() == 'multipolygon'){
var x1,y1,x2,y2;
var horizontal = {belowzero:0,abovezero:0};
var vertical = {belowzero:0,abovezero:0};
for(var j=0; j < c.length; j++){
for(var k=0; k < c[j].length; k++){
for(var l=0; l < c[j][k].length; l++){
var x = c[j][k][l][0];
var y = c[j][k][l][1];
/*if(x < 0 && horizontal.abovezero > horizontal.belowzero){
x = 180;
}
else if(x > 0 && horizontal.abovezero < horizontal.belowzero){
x = -180;
}*/
if(!x1) x1= x;
if(!x2) x2 =x;
if(!y1) y1 = y;
if(!y2) y2 = y;
if(y > y2) y2 = y;
if(y < y1) y1 = y;
if(x < x1) x1 = x;
if(x > x2) x2= x;
if(x > 0){
horizontal.abovezero +=1;
}
else{
horizontal.belowzero +=1;
}
if(y > 0){
vertical.abovezero +=1;
}
else{
vertical.belowzero +=1;
}
}
}
}
//if(f.properties.name == "RUSSIAN FEDERATION")
//console.log(x1,x2);
g.bbox = [];
g.bbox.push(x1);
g.bbox.push(y1);
g.bbox.push(x2);
g.bbox.push(y2);
x1 = false; x2=false;y1=false;y2=false;
}
}
return geojsonbb;
}
,tile2long: function(x,z) {
return (x/Math.pow(2,z)*360-180);
}
,tile2lat: function(y,z) {
var n=Math.PI-2*Math.PI*y/Math.pow(2,z);
return (180/Math.PI*Math.atan(0.5*(Math.exp(n)-Math.exp(-n))));
}
,getLongLatAtXY: function(x,y,eMap){
var res = VismoMapUtils.getLongLatFromMouse(x,y,eMap);
return res;
}
,getSlippyTileNumber: function(lo,la,zoomL,eMap){
var n = Math.pow(2,zoomL);
var x = lo;
var tilex = ((lo + 180)/360) *n;
tilex = Math.floor(tilex);
tiley =(Math.floor((1-Math.log(Math.tan(la*Math.PI/180) + 1/Math.cos(la*Math.PI/180))/Math.PI)/2 *Math.pow(2,zoomL)));
return {x: tilex, y:tiley};
}
,getLocationsFromQuery: function(query,callback){
var that = this;
var fileloadedcallback = function(status,params,responseText,url,xhr){
var response = eval("("+responseText+")");
if(response.responseStatus == 200){
var results = response.responseData.results;
callback(results);
return;
}
};
VismoFileUtils.loadRemoteFile(that.googlelocalsearchurl+query,fileloadedcallback);
}
,getLongLatFromMouse: function(x,y,vismoMap){
var t =vismoMap.getTransformation();
var pos = VismoClickingUtils.undotransformation(x,y,t);
if(vismoMap.settings.projection) {
pos = vismoMap.settings.projection.inversexy(pos.x,pos.y,t);
}
var lo = pos.x;
var la = -pos.y;
/*if(la > 85.0511) la = -la%85.0511;
if(la < -85.0511) la = -la%85.0511;
if(lo < -180) lo = -lo%180;
if(lo > 180) lo = - lo%180;
*/
return {latitude: la, longitude: lo};
}
,_radToDeg: function(rad){
return rad / (Math.PI /180);
},
_degToRad: function(deg) {
//return ((deg + 180)/360) ;
return (deg * Math.PI) / 180.0;
},
fitgeojsontocanvas: function(json,canvas){ /*canvas must have style width and height properties, returns an VismoTransformation*/
var view ={};
var f =json.features;
for(var i=0; i < f.length; i++){
var c = f[i].geometry.coordinates;
for(var j=0; j < c.length; j++ ){
for(var k=0; k < c[j].length; k++){
for(var l=0; l < c[j][k].length;l++){
var x =c[j][k][l][0];
var y = c[j][k][l][1];
if(!view.x1 || x <view.x1) {
view.x1 = x;
}
else if(!view.x2 || x >view.x2) {
view.x2 = x;
}
if(!view.y1 || y <view.y1) {
view.y1 = y;
}
else if(!view.y2 || y >view.y2) {
view.y2 = y;
}
}
}
}
}
if(!json.transform) json.transform ={};
if(!json.transform.scale) json.transform.scale = {x:1, y:1};
if(!json.transform.translate) json.transform.translate = {x:0,y:0};
var canvasx = parseFloat(canvas.style.width);
var canvasy =parseFloat(canvas.style.height);
view.center = {};
view.width = (view.x2 - view.x1);
view.height = (view.y2 - view.y1)
view.center.x = view.x2 - (view.width/2);
view.center.y = view.y2 - (view.height/2);
//console.log(view.center.y, view.height);
var scale = 1,temp;
var tempx = parseFloat(canvasx/view.width);
var tempy = parseFloat(canvasy/view.height);
if(tempx < tempy) temp = tempx; else temp = tempy;
var transform = {scale:{},translate:{}};
transform.scale.x = temp;
transform.scale.y = temp;
transform.boundingBox = view;
transform.translate.x = -view.center.x;
transform.translate.y = view.center.y;//view.center.y;
return transform;
},
/*does not yet support undoing rotating */
_testCanvas: function(ctx){
ctx.beginPath();
ctx.arc(75,75,50,0,Math.PI*2,true); // Outer circle
ctx.moveTo(110,75);
ctx.arc(75,75,35,0,Math.PI,false); // Mouth (clockwise)
ctx.moveTo(65,65);
ctx.arc(60,65,5,0,Math.PI*2,true); // Left eye
ctx.moveTo(95,65);
ctx.arc(90,65,5,0,Math.PI*2,true); // Right eye
ctx.stroke();
},
_undospherify: function (x,y,transformation,radius){
var pos= this._spherifycoordinate(x,y,transformation);
var latitude = Math.asin(y / radius);
var longitude = Math.asin(parseFloat(x / radius) / Math.cos(latitude));
//if(transformation.rotate.z && longitude != 'NaN')longitude -= transformation.rotate.z;
//longitude = longitude % (6.28318531);
//if(longitude < 0) longitude = longitude
if(transformation.rotate) {
var r =transformation.rotate.z;
//console.log("from",longitude);
longitude +=r;
//longitude =longitude% (6.28318531);
}
var lon = VismoMapUtils._radToDeg(longitude);
var lat = VismoMapUtils._radToDeg(latitude);
//console.log("to",longitude,r,lon);
return {x:lon,y:lat};
},
_spherifycoordinate: function(lon,lat,transformation,radius){
//http://board.flashkit.com/board/archive/index.php/t-666832.html
var utils = VismoMapUtils;
var res = {};
var longitude = VismoMapUtils._degToRad(lon);
var latitude = VismoMapUtils._degToRad(lat);
var wraplat = false;
// assume rotate values given in radians
if(transformation && transformation.rotate){
//latitude += transformation.rotate.x;
var rotation =transformation.rotate.z;
//rotation = transformation.translate.x;
if(rotation){
var r =parseFloat(rotation);
var newl =parseFloat(longitude+r);
//console.log(longitude,"->",newl,longitude,r,transformation.rotate.z);
longitude +=r;
}
if(transformation.rotate.y){
latitude += parseFloat(transformation.rotate.y);
/*var limit =VismoMapUtils._degToRad(85);
if(latitude <-limit){
latitude += (2 * limit);
res.movedNorth = true;
}
if(latitude > limit){
latitude -= (2 * limit);
res.movedSouth = true;
}
*/
//latitude = latitude % 6.28318531;
}
}
// latitude is 90-theta, where theta is the polar angle in spherical coordinates
// cos(90-theta) = sin(theta)
// sin(90-theta) = cos(theta)
// to transform from spherical to cartesian, we would normally use radius*Math.cos(theta)
// hence in this case we use radius*Math.sin(latitude)
// similarly longitude is phi-180, where phi is the azimuthal angle
// cos(phi-180) = -cos(phi)
// sin(phi-180) = -sin(phi)
// to transform from spherical to cartesian, we would normally use radius*Math.sin(theta)*Math.cos(phi)
// we must exchange for theta as above, but because of the circular symmetry
// it does not matter whether we multiply by sin or cos of longitude
longitude = longitude % 6.28318531; //360 degrees
res.y = (radius) * Math.sin(latitude);
//console.log(latitude);
//if(wraplat) res.y = ["M",res.y];
/*
if(latitude > 85.0511){
res.y = (-radius) * Math.sin(latitude);
}
else{
res.y = (radius) * Math.sin(latitude);
}
*/
//if(latitude > 85.0511)
if(longitude < 1.57079633 || longitude > 4.71238898){//0-90 (right) or 270-360 (left) then on other side
res.x = (radius) * Math.cos(latitude) * Math.sin(longitude);
}
else{
//console.log(longitude,"bad",transformation.rotate.z);
res.x = false;
}
return res;
}
};Array.prototype.contains = function(item)
{
return this.indexOf(item) != -1;
};
function mozillaSaveFile(filePath,content)
{
if(window.Components) {
try {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
file.initWithPath(filePath);
if(!file.exists())
file.create(0,0664);
var out = Components.classes["@mozilla.org/network/file-output-stream;1"].createInstance(Components.interfaces.nsIFileOutputStream);
out.init(file,0x20|0x02,00004,null);
out.write(content,content.length);
out.flush();
out.close();
return true;
} catch(ex) {
return false;
}
}
return null;
}
var VismoFileUtils= {
saveFile: function(fileUrl,content)
{
mozillaSaveFile(fileUrl,content); return;
jQuery.file.save({fileUrl:fileUrl,content:content});
}
,convertUriToUTF8:function(uri,charSet)
{
if(window.netscape == undefined || charSet == undefined || charSet == "")
return uri;
try {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var converter = Components.classes["@mozilla.org/intl/utf8converterservice;1"].getService(Components.interfaces.nsIUTF8ConverterService);
} catch(ex) {
return uri;
}
return converter.convertURISpecToUTF8(uri,charSet);
}
,getLocalPath:function(origPath)
{
var originalPath = VismoFileUtils.convertUriToUTF8(origPath,"UTF-8");
// Remove any location or query part of the URL
var argPos = originalPath.indexOf("?");
if(argPos != -1)
originalPath = originalPath.substr(0,argPos);
var hashPos = originalPath.indexOf("#");
if(hashPos != -1)
originalPath = originalPath.substr(0,hashPos);
// Convert file://localhost/ to file:///
if(originalPath.indexOf("file://localhost/") == 0)
originalPath = "file://" + originalPath.substr(16);
// Convert to a native file format
var localPath;
if(originalPath.charAt(9) == ":") // pc local file
localPath = unescape(originalPath.substr(8)).replace(new RegExp("/","g"),"\\");
else if(originalPath.indexOf("file://///") == 0) // FireFox pc network file
localPath = "\\\\" + unescape(originalPath.substr(10)).replace(new RegExp("/","g"),"\\");
else if(originalPath.indexOf("file:///") == 0) // mac/unix local file
localPath = unescape(originalPath.substr(7));
else if(originalPath.indexOf("file:/") == 0) // mac/unix local file
localPath = unescape(originalPath.substr(5));
else if(originalPath.indexOf("http") == 0){ //jon hack for online
var end =originalPath.lastIndexOf("/");
localPath = unescape(originalPath.substr(0,end+1));
}
else // pc network file
localPath = "\\\\" + unescape(originalPath.substr(7)).replace(new RegExp("/","g"),"\\");
return localPath;
}
,loadRemoteFile: function(url,callback,params,headers,data,contentType,username,password,allowCache)
{
//callback parameters: status,params,responseText,url,xhr
return this._httpReq("GET",url,callback,params,headers,data,contentType,username,password,allowCache);
}
/*currently doesnt work with jpg files - ok formats:gifs pngs*/
,saveImageLocally: function(sourceurl,dest,dothiswhensavedlocally,dothiswhenloadedfromweb) {
var localPath = VismoFileUtils.getLocalPath(document.location.toString());
var savePath;
if((p = localPath.lastIndexOf("/")) != -1) {
savePath = localPath.substr(0,p) + "/" + dest;
} else {
if((p = localPath.lastIndexOf("\\")) != -1) {
savePath = localPath.substr(0,p) + "\\" + dest;
} else {
savePath = localPath + "/" + dest;
}
}
var onloadfromweb = function(status,params,responseText,url,xhr){
try{
if(dothiswhenloadedfromweb){
dothiswhenloadedfromweb(url);
}
//console.log("VismoFileUtil.saveFile doesnt work for iamges it might seem",savePath);
VismoFileUtils.saveFile(savePath,responseText);
}
catch(e){
console.log("error saving locally.."+ e);
}
};
var onloadlocally = function(responseText,url,xhr){
if(dothiswhensavedlocally){
dothiswhensavedlocally(dest);
}
};
try{
var r = jQuery.get(dest,null,onloadlocally);
if(r.status == 404) throw "404 error";
}
catch(e){//couldnt load probably doesn't exist!
VismoFileUtils.loadRemoteFile(sourceurl,onloadfromweb,null,null,null,null,null,null,true);
}
}
,_httpReq: function (type,url,callback,params,headers,data,contentType,username,password,allowCache)
{
var x = null;
try {
x = new XMLHttpRequest(); //# Modern
} catch(ex) {
try {
x = new ActiveXObject("Msxml2.XMLHTTP"); //# IE 6
} catch(ex2) {
}
}
if(!x)
return "Can't create XMLHttpRequest object";
x.onreadystatechange = function() {
try {
var status = x.status;
} catch(ex) {
status = false;
}
if(x.readyState == 4 && callback && (status !== undefined)) {
if([0, 200, 201, 204, 207].contains(status))
callback(true,params,x.responseText,url,x);
else{
callback(false,params,null,url,x);
}
x.onreadystatechange = function(){};
x = null;
}
};
try {
if(window.Components && window.netscape && window.netscape.security && document.location.protocol.indexOf("http") == -1)
window.netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
if(!allowCache)
url = url + (url.indexOf("?") < 0 ? "?" : "&") + "nocache=" + Math.random();
else{
url = url + (url.indexOf("?") < 0 ? "?" : "&");
}
x.open(type,url,true,username,password);
if(data)
x.setRequestHeader("Content-Type", contentType || "application/x-www-form-urlencoded");
if(x.overrideMimeType)
x.setRequestHeader("Connection", "close");
if(headers) {
for(var n in headers)
x.setRequestHeader(n,headers[n]);
}
// x.setRequestHeader("X-Requested-With", "TiddlyWiki " + formatVersion());
x.overrideMimeType('text/plain; charset=x-user-defined');
x.send(data);
} catch(ex) {
//console.log(ex);
//throw ex;
}
return x;
},
_getXML:function(str) {
if(!str)
return null;
var errorMsg;
try {
var doc = new ActiveXObject("Microsoft.XMLDOM");
doc.async="false";
doc.loadXML(str);
}
catch(e) {
try {
var parser= new DOMParser();
var doc = parser.parseFromString(str,"text/xml");
}
catch(e) {
return e.message;
}
}
return doc;
}
,getChildNodeValue: function(ofThisNode){
var value= "";
if(ofThisNode.childNodes){
for(var k=0; k < ofThisNode.childNodes.length; k++){
if(ofThisNode.childNodes[k].nodeValue){
value += ofThisNode.childNodes[k].nodeValue;
}
}
}
return value;
}
};/*some conversion functions that convert to geojson */
var VismoConversion ={
niaveGeoJsonFlatten: function(geojson,niaveness){
var newdata = geojson;
var coordsDropped = 0;
for(var i=0; i < newdata.features.length; i++){
var g = newdata.features[i].geometry;
if(g.type == 'MultiPolygon'){
for(var ij =0; ij < g.coordinates.length; ij++){
for(var j=0; j < g.coordinates[ij].length; j++){
var bettercoords = [];
var every = 0;
if(g.coordinates[ij][j].length > 50){
for(var k=0; k < g.coordinates[ij][j].length; k++){
var c = g.coordinates[ij][j][k];
if(every == 0){
var x = parseFloat(c[0]);
var y = parseFloat(c[1]);
bettercoords.push([x,y]);
every= niaveness;
}
else{
every -= 1;
}
}
coordsDropped += (g.coordinates[ij][j].length - bettercoords.length);
g.coordinates[ij][j] = bettercoords;
}
}
}
}
}
console.log(coordsDropped,"dropped");
return newdata;
}
,svgToGeoJson: function(svg,canvas){
var svgxml = VismoFileUtils._getXML(svg);
var res = VismoMapSVGUtils.convertSVGToMultiPolygonFeatureCollection(svgxml);
//res = VismoMapUtils.fitgeojsontocanvas(res,canvas);
//console.log(res.boundingBox);
//res
//work out here where origin should be (half of the maximum width of the svg coordinate space should be 0)
return res;
},
_kmlPolygonToFeature: function(xmlNode,feature){
var geocoordinates = [];
var polyChildren =xmlNode.childNodes;
for(var k=0; k < polyChildren.length; k++){
var fail = true;
if(polyChildren[k].tagName =='outerBoundaryIs'){
var outerChildren =polyChildren[k].childNodes;
for(var l=0; l < outerChildren.length; l++){
if(outerChildren[l].tagName == 'LinearRing'){
var ringChildren =outerChildren[l].childNodes;
for(var m=0; m < ringChildren.length; m++){
if(ringChildren[m].tagName == 'coordinates'){
var geometry = VismoFileUtils.getChildNodeValue(ringChildren[m]);
geometry = geometry.trim();
var coords = geometry.split(" "); //\n?
for(var n=0; n < coords.length; n+= 1){
var values = coords[n].split(",");
var longitude= parseFloat(values[0]);
var latitude = parseFloat(values[1]);
var altitude = parseFloat(values[2]);
geocoordinates.push([longitude,latitude]);
}
if(coords.length ==0){
return false;
}
else{
fail = false;
}
feature.geometry.coordinates.push([geocoordinates]);
}
}
}
}
}
}
if(!feature){
fail = true;
}
else if(feature.geometry.coordinates[0].length == 0){
fail = true;
}
else if(feature.geometry.coordinates[0][0].length == 1){
fail = true;
}
if(fail) {
return false;
}
else{
return feature;
}
}
,kmlToGeoJson: function(kml){
var geojson = {type:"FeatureCollection", features:[]};
var xml =VismoFileUtils._getXML(kml);
var items = xml.getElementsByTagName("Placemark");
for(var i=0; i < items.length; i++){
var feature = {type:'Feature', geometry:{type:'MultiPolygon', coordinates:[]},properties:{'name':'georss'}};
var att = items[i].childNodes;
for(var j=0; j < att.length; j++){
var fail = false;
if(att[j].tagName == 'name' && att[j].firstChild){
feature.properties.name =att[j].firstChild.nodeValue;
}
if(att[j].tagName == 'Polygon'){
var succeeded = this._kmlPolygonToFeature(att[j],feature);
if(succeeded){
feature = succeeded;
}
else{
fail = true;
}
}
if(att[j].tagName == 'MultiGeometry'){
var children = att[j].childNodes;
for(var k=0; k < children.length; k++){
if(children[k].tagName == 'Polygon'){
var succeeded = this._kmlPolygonToFeature(children[k],feature);
if(succeeded){
feature = succeeded;
}
else{
fail = true;
}
}
}
}
}
//console.log("ere",fail);
//if(!fail)
//console.log(feature.geometry.coordinates.length);
if(!fail && feature && feature.geometry.coordinates.length > 0) {
geojson.features.push(feature);
}
}
return geojson;
}
,geoRssToGeoJson : function (georss){
var geojson = {type:"FeatureCollection", features:[]};
var xml =VismoFileUtils._getXML(georss);
var items = xml.getElementsByTagName("item");
for(var i=0; i < items.length; i++){
var feature = {type:'Feature', geometry:{type:'MultiPolygon', coordinates:[]},properties:{'name':'georss'}};
var fail = false;
var att = items[i].childNodes;
for(var j=0; j < att.length; j++){
if(att[j].tagName == 'title' && att[j].firstChild){
feature.properties.name =att[j].firstChild.nodeValue;
}
if(att[j].tagName == 'description' && att[j].firstChild){
feature.properties.description =att[j].firstChild.nodeValue;
}
if(att[j].tagName == 'georss:polygon'){
var geocoordinates = [];
//console.log(att[j].innerHTML,att[j].firstChild,"inner");
var geometry = VismoFileUtils.getChildNodeValue(att[j]);
geometry = geometry.trim();
geometry = geometry.replace(/ +/g, " ");
geometry = geometry.replace(/\n/g, "");
var values = geometry.split(" ");
if(values[0] != values[values.length-2] |values[1] != values[values.length-1]){
values.push(values[0]);
values.push(values[1]);
}
for(var k=0; k < values.length - 1; k+= 2){
var latitude = parseFloat(values[k]);
var longitude= parseFloat(values[k+1]);
geocoordinates.push([longitude,latitude]);
}
feature.geometry.coordinates.push([geocoordinates]);
}
}
if(!fail){
geojson.features.push(feature);
}
else{
//console.log("Unable to construct feature " +feature.properties.name+". Invalid georss coordinates: first and last coordinates should be same. ");
}
}
return geojson;
}
};var VismoClickingUtils = {
//to be implemented..
inVisibleArea: function(vismoCanvas,vismoShape){
var bb = vismoShape.getBoundingBox();
return true;
}
,scrollXY: function(){
var scrOfX = 0, scrOfY = 0;
if( typeof( window.pageYOffset ) == 'number' ) {
//Netscape compliant
scrOfY = window.pageYOffset;
scrOfX = window.pageXOffset;
} else if( document.body && ( document.body.scrollLeft || document.body.scrollTop ) ) {
//DOM compliant
scrOfY = document.body.scrollTop;
scrOfX = document.body.scrollLeft;
} else if( document.documentElement && ( document.documentElement.scrollLeft || document.documentElement.scrollTop ) ) {
//IE6 standards compliant mode
scrOfY = document.documentElement.scrollTop;
scrOfX = document.documentElement.scrollLeft;
}
return {x: scrOfX,y: scrOfY};
}
,getRealXYFromMouse: function(e,t){
var newpos =VismoClickingUtils.getMouseFromEvent(e);
newpos = VismoClickingUtils.undotransformation(newpos.x,newpos.y,t);
return newpos;
}
,undotransformation: function(x,y,transformation){ //porting to VismoTransformations?
return VismoTransformations.undoTransformation(x,y,transformation);
}
,resolveTarget:function(e)
{
if(!e) e = window.event;
var obj;
if(e && e.srcElement){
obj = e.srcElement;
}
else if(e.target)
obj = e.target;
else{
obj = false;
}
try{
var x = obj.parentNode;
}catch(e){return false;}
/*
if(obj && obj.nodeType && obj.nodeType == 3) // defeat Safari bug
obj = obj.parentNode;
*/
/*try{
var x = obj.parentNode;
}
catch(e){return false;};*/
return obj;
//return obj;
}
,getMouseFromEvent : function(e,target){
if(!e) e = window.event;
if(!target){
var target = this.resolveTargetWithVismo(e);
if(!target)return false;
}
var offset = jQuery(target).offset();
var i;
if(typeof(offset.left) != 'number') return false;
var scroll = this.scrollXY(e);
x = e.clientX + scroll.x;
y = e.clientY + scroll.y;
//alert(x +"/"+y);
x -= offset.left;
y-= offset.top;
return {'x':x, 'y':y};
}
,getMouseFromEventRelativeToTarget : function(e,target){
if(!e) e = window.event;
if(!target)return false;
var offset = jQuery(target).offset();
if(!offset.left) return false;
var scroll = this.scrollXY();
x = e.clientX + scroll.x - offset.left;
y = e.clientY + scroll.y - offset.top;
return {'x':x, 'y':y};
}
,resolveTargetWithVismo: function(e)
{
var node = VismoClickingUtils.resolveTarget(e);
if(!node)return false;
var hasVismo = false;
while(!hasVismo && node != document && node.parentNode && node.parentNode != document){
if(node.vismoCanvas || node.vismoController || node.vismoClicking){
hasVismo = true;
}
else{
node= node.parentNode;
}
}
if(!node) return false;
return node;
}
,getMouseFromEventRelativeToElement: function (e,x,y,target){
if(!e) e = window.event;
var offset = jQuery(target).offset();
if(!offset.left) return false;
var scroll = this.scrollXY();
oldx = e.clientX + scroll.x - offset.left;
oldy = e.clientY + scroll.y - offset.top;
var pos = {'x':oldx, 'y':oldy};
if(!pos) return false;
pos.x -= x;
pos.y -= y;
return pos;
}
,getMouseFromEventRelativeTo: function (e,x,y){
var pos = this.getMouseFromEvent(e);
if(!pos) return false;
pos.x -= x;
pos.y -= y;
return pos;
}
,getMouseFromEventRelativeToElementCenter: function(e){ /*redundant?? */
var w,h;
var target = this.resolveTargetWithVismo(e);
if(!target)return;
if(target.style.width)
w = parseInt(target.style.width);
else if(target.width)
w =parseInt(target.width);
if(target.style.height)
h = parseInt(target.style.height);
else if(target.height)
h = parseInt(target.height);
if(!w || !h) throw "target has no width or height (vismomaputils)";
return this.getMouseFromEventRelativeTo(e,w/2,h/2);
}
};
var VismoTransformations= {
clone: function(transformation){
var t = {};
t.translate = {x:0,y:0};
t.scale = {x:1,y:1};
if(transformation.translate && transformation.translate.x){
t.translate.x = transformation.translate.x;
t.translate.y = transformation.translate.y;
}
if(transformation.scale && transformation.scale.x){
t.scale.x = transformation.scale.x;
t.scale.y = transformation.scale.y;
}
return t;
}
,applyTransformation: function(x,y,t){
var res= {};
res.x = x;
res.y = y;
if(t.translate){
res.x += t.translate.x;
res.y += t.translate.y;
}
if(t.scale){
res.x *= t.scale.x;
res.y *= t.scale.y;
}
if(t.origin){
res.x += t.origin.x;
res.y += t.origin.y;
}
return res;
}
,mergeTransformations: function(a,b){
if(!b) return a;
if(!a) return b;
var result = {};
var i;
for(i in a){
result[i] = a[i];
}
for(i in b){
if(result[i]){
var oldt = result[i];
var newt = b[i];
result[i].x = oldt.x + newt.x;
result[i].y = oldt.y + newt.y;
}
else{
result[i] = b[i];
}
}
return result;
}
,undoTransformation: function(x,y,transformation){
var pos = {};
var t =transformation;
var tr =t.translate;
var s = t.scale;
var o = t.origin;
if(s ===false || o ===false || tr ===false) return false;
if(x ===false || y ===false)return false;
pos.x = x - o.x;
pos.y = y -o.y;
//pos.x -= x;
//pos.y += y;
if(pos.x !== 0)
pos.x /= s.x;
if(pos.y !== 0)
pos.y /= s.y;
pos.x -= tr.x;
pos.y -= tr.y;
return pos;
}
,getXY: function(e,t){
var pos =VismoClickingUtils.getMouseFromEvent(e);
return this.undoTransformation(pos.x,pos.y,t);
}
,create: function(options){
var transformation= {};
var i;
for(i in options){
transformation[i] = options[i];
}
var s = transformation.scale;
var t = transformation.translate;
transformation["cache"] = {id1:[s.x,",",s.y].join(""),id2:[t.x,",",t.y].join("")};
return transformation;
}
};var Vismo = {store:{Canvas:{}}};
var VismoCanvas = function(element,options){
this._referenceid = Math.random();
Vismo.store.Canvas[this._referenceid] = this;
this._lastTransformation = {scale:{}};
if(element.length){ //for jquery
var result = [];
for(var i=0; i < element.length; i++){
var x = new VismoCanvas(element[i],options);
result.push(x);
}
return x;
}
this.className = "VismoCanvas";
this._idtoshapemap = {};
if(!options) options = {};
if(typeof element == 'string') element= document.getElementById(element);
if(!element) throw "Element doesn't exist!";
var canvaswidth = jQuery(element).width();
var canvasheight = jQuery(element).height();
element.style.width = canvaswidth;
element.style.height = canvasheight;
if(element.vismoClicking) {
var update = element.vismoClicking;
return update;
}
if(!options.pointsize){
options.pointsize = 5;
}
this.options = options;
var wrapper = element;
this.settings = {};
this.settings.browser = !VismoUtils.browser.isIE ? 'good' : 'ie'
this.settings.globalAlpha = 1;
var canvas;
var hideoverflow;
if(this.settings.browser =='good'){
canvas = document.createElement('canvas');
canvas.className = "VismoCanvasRenderer";
hideoverflow = canvas;
}
else
{
hideoverflow = document.createElement("div");
canvas = document.createElement('div');
canvas.className = "VismoIECanvas VismoCanvasRenderer";
canvas.style.setAttribute('cssText', 'position:absolute;left:0px;top:0px;', 0);
hideoverflow.appendChild(canvas);
}
//.VismoIECanvas
var width =parseInt(wrapper.style.width);
var height =parseInt(wrapper.style.height);
canvas.width = width;
canvas.height = height;
this.setTransformation({translate:{x:0,y:0},scale:{x:1,y:1},origin:{x:canvaswidth/2, y:canvasheight/2}});
if(!element.className)element.className = "VismoCanvas";
jQuery(canvas).css({width:width, height:height,'z-index':1,position:'absolute'});
element.appendChild(hideoverflow);
jQuery(hideoverflow).css({width:width, height:height,position:"absolute",overflow:"hidden",left:"0px",top:"0px"});
var labels = document.createElement("div");
jQuery(labels).css({position:"absolute","z-index":9});
labels.className = "VismoLabels";
wrapper.appendChild(labels);
this.labelHolder = labels;
this.labels = [];
this.canvas = canvas;
this.memory = [];
element.vismoClicking = true;//this;//true;//this
jQuery(this.canvas).mousedown(function(e){e.preventDefault();});
this.wrapper = wrapper;
this._setupMouse();
var vc = this;
if(options.vismoController){
if(!options.vismoController.handler){
options.vismoController.handler = function(t){
vc.transform(t);
}
}
this.vismoController = new VismoController(this.getDomElement(),options.vismoController);
}
this.mouse({down:options.mousedown,up:options.mouseup,move:options.move,dblclick:options.dblclick,keypress:options.keypress});
var tooltipfunction;
if(options.tooltipfunction){
if(typeof options.tooltipfunction == 'boolean'){
tooltipfunction = function(el,s){
if(s){
el.innerHTML = "cool"+s.getProperty("id");}
}
}
else{
tooltipfunction = options.tooltipfunction;
}
this.addTooltip(tooltipfunction)
}
if(options.shapes) {
for(var i=0; i < options.shapes.length; i++){
this.add(options.shapes[i]);
}
this.render();
}
var x = window.onbeforeunload;
var that = this;
window.onbeforeunload =function(){
that.teardown();
x();
};
};
VismoCanvas.prototype = {
teardown: function(){
VismoUtils.scrubNode(this.canvas);
VismoUtils.scrubNode(this.wrapper);
VismoUtils.scrubNode(this.labelHolder);
jQuery(this.canvas).unbind("mousedown");
this.wrapper.onmouseout = null;
this.wrapper.onmouseover = null;
}
,getDomElement: function(args){
return this.wrapper;
}
,addTooltip: function(args){
var addContent = arguments[0];
var wrapper = this.wrapper;
if(addContent) this.tooltipAddContent = addContent;
if(!this.tooltip){
var tooltip = document.createElement("div");
jQuery(tooltip).css({position:"absolute","z-index":1000,display:"none"});
tooltip.className = "VismoTooltip";
jQuery(tooltip).mousedown(function(e){e.preventDefault();if(wrapper && wrapper.onmousedown)wrapper.onmousedown(e);});
jQuery(tooltip).mousemove(function(e){e.preventDefault();});
jQuery(this.wrapper).parent().append(tooltip);
this.tooltip = tooltip;
}
if(!this.tooltipAdded){
var move= this.onmousemove;
var that = this;
var lastshape;
var newmove = function(e,shape){
if(!e) e = window.event;
if(!that.tooltip) return;
jQuery(that.tooltip).html("");
if(shape && lastshape != shape){
var bb = shape.getBoundingBox();
//var pos = VismoClickingUtils.getMouseFromEvent(e);
if(that.tooltipAddContent)that.tooltipAddContent(that.tooltip,shape);
var pos = VismoTransformations.applyTransformation(bb.x2,bb.y1,that.getTransformation())
//var pos= {x: bb.center.x, y:bb.center.y};
var w = jQuery(that.wrapper).width();
var h = jQuery(that.wrapper).height();
var off = jQuery(that.wrapper).offset();
if(pos.x > off.left + w) pos.x = off.left + w;
//jQuery(that.tooltip).css({top:0, right:0});
}
if(that.tooltipAddContent && shape){
that.tooltipAddContent(that.tooltip,shape);
lastshape = shape;
jQuery(that.tooltip).css({display:""});
}
else{
jQuery(that.tooltip).css({display:"none"});
}
if(move)move(e,shape);
};
this.onmousemove = newmove;
this.tooltipAdded = true;
}
}
,getXYWindow: function(args){
var e = arguments[0];
var t = this.getTransformation();
var pos = this.getXY(e);
return VismoTransformations.applyTransformation(pos.x,pos.y,t);
}
,getXY: function(args){
var e = arguments[0];
return VismoTransformations.getXY(e,this.getTransformation());
}
,mouse: function(args){
if(!args){
return {up: this.onmouseup, down: this.onmousedown, move: this.onmousemove, dblclick: this.ondblclick,keypress:this.onkeypress};
}
else{
var args = arguments[0];
if(args.down)this.onmousedown = args.down;
if(args.up)this.onmouseup = args.up;
if(args.move)this.onmousemove= args.move;
if(args.dblclick) this.ondblclick = args.dblclick;
if(args.keypress) this.onkeypress = args.keypress;
//if(this.madeMoveable) this.makeMoveable();
//if(this.tooltipAdded) this.addTooltip();
}
}
,_setupMouse: function(args){
var that = this;
this.onmousedown = function(e,s,pos){};
this.onmouseup = function(e,s,pos){};
this.onmousemove = function(e,s,pos){};
this.ondblclick = function(e,s,pos){};
this.onkeypress = function(e){};
this._applyMouseBehaviours(this.wrapper);
for(var i =0; i < this.wrapper.childNodes.length; i++){
var child = this.wrapper.childNodes[i];
//this._applyMouseBehaviours(child);
}
}
,_applyMouseBehaviours: function(args){
var el = arguments[0];
var that = this;
var newbehaviour = function(e){
//var t = VismoClickingUtils.resolveTargetWithVismo(e);
//if(t && t.getAttribute("class") == 'vismoControl') return false;
var shape = that.getShapeAtClick(e,el);
return shape;
};
var applymice = function(el){
var down = el.onmousedown;
var up = el.onmouseup;
var mv = el.onmousemove;
var dblclick =el.ondblclick;
this.initialKeyPress = window.onkeypress;
//el.oncontextmenu=function(args) { return false};
el.onmouseover = function(e){
if(!that.keypressactive) {
that.keypressactive = true;
window.onkeypress =function(e){
that.onkeypress(e);
if(that.initialKeyPress)that.initialKeyPress(e);
}
document.onkeypress = function(e){if(!e) e= window.event;if(that.initialKeyPress)that.initialKeyPress(e);if(!e) e= window.event;var s = newbehaviour(e);
if(that.onkeypress)that.onkeypress(e,s)
};
}
};
el.onmouseout = function(e){if(!e) e= window.event;that.keypressactive = false;};
jQuery(el).mousedown(function(e){
//console.log("md",el);
var s = newbehaviour(e);
if(s){
if(s.getProperty("onmousedown")){
s.getProperty("onmousedown")(e,s);
if(that.onmousedown)that.onmousedown(e,s);
}
else{
if(that.onmousedown)that.onmousedown(e,s);
}
}
else {
//console.log("ic");
if(that.onmousedown)that.onmousedown(e,s);
if(down)down(e,s);
}
});
jQuery(el).dblclick(function(e){
if(!e) e= window.event;
var s = newbehaviour(e);
if(s) {
if(s.getProperty("ondblclick")){
s.getProperty("ondblclick")(e,s);
}
else if(that.ondblclick){
that.ondblclick(e,s);
}
else{
}
}
else {
if(that.ondblclick){
that.ondblclick(e,s);
}
if(dblclick){
dblclick(e,s);
}
}
});
jQuery(el).mouseup(function(e){
//console.log("mu",el);
var s = newbehaviour(e);
if(s){
if(s.getProperty("onmouseup")){
s.getProperty("onmouseup")(e,s);
if(that.onmouseup)that.onmouseup(e,s);
}
else{
if(that.onmouseup)that.onmouseup(e,s);
}
}
else{
if(that.onmouseup)that.onmouseup(e,s);
if(up)up(e,s);
}
});
var defaultCursor;
jQuery(el).mousemove(function(e){ if(!e) e= window.event;var s = newbehaviour(e);
if(!VismoUtils.browser.isIE){
if(jQuery(el).hasClass("overVismoShape")) jQuery(el).removeClass("overVismoShape");
}
if(!VismoUtils.browser.isIE){
if(jQuery(el).hasClass("overVismoPoint"))jQuery(el).removeClass("overVismoPoint");
}
if(s && !s.getProperty("unclickable")){
if(that.ondblclick || that.onmousedown || that.onmouseup) {
var sh;
if(s){
sh = s.getShape();
if(!VismoUtils.browser.isIE &&sh == "point") jQuery(el).addClass("overVismoPoint");
}
if(!VismoUtils.browser.isIE && !jQuery(el).hasClass("panning") && !jQuery(el).hasClass("zooming"))jQuery(el).addClass("overVismoShape");
}
if(s.getProperty("onmousemove"))s.getProperty("onmousemove")(e,s);
}
else{
//el.style.cursor = defaultCursor;
}
if(that.onmousemove)that.onmousemove(e,s);
if(mv)mv(e,s);
});
};
applymice(el);
}
,getDimensions: function(args){
return {width: this.width() , height: this.height()};
}
,height: function(){
return parseInt(this.canvas.style.height);
},
width: function(){
return parseInt(this.canvas.style.width);
}
,resize: function(args){
var width = arguments[0]; var height=arguments[1];
if(this.canvas.getAttribute("width")){
this.canvas.width = width;
this.canvas.height = height;
}
jQuery(this.hideoverflow).css({height:height,width:width});
jQuery(this.wrapper).css({height:height,width:width});
jQuery(this.canvas).css({height:height,width:width});
}
,setTransparency: function(args){
var alpha = arguments[0];
this.settings.globalAlpha = alpha
}
,_setupCanvasEnvironment: function(args){
if(VismoUtils.browser.isIE) return;
var ctx = this.canvas.getContext('2d');
var s =this.getTransformation().scale;
if(s && s.x)ctx.lineWidth = (0.5 / s.x);
ctx.globalAlpha = this.settings.globalAlpha;
ctx.clearRect(0,0,this.canvas.width,this.canvas.height);
ctx.lineJoin = 'round'; //miter or bevel or round
}
,clear: function(args){
var deleteMemory = arguments[0];
if(deleteMemory){
this.clearMemory();
}
this._maxX = 0;
this._maxY = 0;
if(!this.canvas.getContext) {
return;
}
var ctx = this.canvas.getContext('2d');
ctx.clearRect(0,0,this.canvas.width,this.canvas.height);
}
,ie_render: function(args){
var projection= arguments[0];
VismoTimer.start("VismoCanvas.ie_render");
//this.render = this.ie_render;
var that = this;
var transformation = this.getTransformation();
if(this.options.beforeRender) this.options.beforeRender(this);
if(transformation.scale.x) sc = transformation.scale.x; else sc = 1;
//determine point size
var ps = this.options.pointsize / parseFloat(sc);
tran = transformation;
var o = tran.origin,t = tran.translate, s = tran.scale;
jQuery(this.canvas).css({left:o.x+(t.x*s.x),top:o.y +(s.y*t.y),zoom:s.x});
var mem =that.memory;
var firstTime = false;
var appendTo;
if(that.canvas.childNodes.length == 0){
firstTime = true;
appendTo = document.createElement("div");
}
else{
appendTo = that.canvas;
}
var lastT = this._lastTransformation.scale;
var shapes = this._lastTransformation.shapes;
if(lastT.x ===s.x && lastT.y === s.y && this.memory.length == shapes){
tran = false; //stop a transformation from being applied we've covered it here
}
var globalAlpha =that.settings.globalAlpha;
for(var i=0; i < mem.length; i++){
var vs =mem[i];
var st = vs.properties.shape
//if(vs.optimise(appendTo,transformation,projection)){
if(st == 'domElement')tran = transformation;
vs.render(that.canvas,tran,projection,true,that.settings.browser,ps);
if(vs.vmlfill && !vs.vmlfill.opacity && globalAlpha) {
vs.vmlfill.opacity =globalAlpha;
}
//}
/*
var lookahead = function(){
var newtransformation = VismoUtils.clone(transformation);
newtransformation.scale.x *=2;
newtransformation.scale.y *= 2;
vs.optimise(appendTo,newtransformation,projection,true);
};
window.setTimeout(lookahead,1000);
*/
}
this._lastTransformation = {scale:{x:s.x,y:s.y},shapes:this.memory.length};
if(firstTime){
that.canvas.appendChild(appendTo.cloneNode(true));
}
VismoTimer.end("VismoCanvas.ie_render");
}
,canvas_render: function(args){
//console.log(this.getDomElement(),this.transformation);
var projection = arguments[0];
this.render = this.canvas_render;
var that = this;
var transformation = this.getTransformation();
if(this.options.beforeRender) this.options.beforeRender(this);
if(transformation.scale.x) sc = transformation.scale.x; else sc = 1;
//determine point size
var ps = this.options.pointsize / parseFloat(sc);
var appendTo;
var mem =that.getMemory();
this._setupCanvasEnvironment();
var ctx = that.canvas.getContext('2d');
ctx.save();
tran = false;
if(transformation){
var o = transformation.origin;
var tr = transformation.translate;
var s = transformation.scale;
var r = transformation.rotate;
if(o && s && tr){
ctx.translate(o.x,o.y);
ctx.scale(s.x,s.y);
ctx.translate(tr.x,tr.y);
}
if(r && r.x)ctx.rotate(r.x);
}
appendTo = that.canvas;
for(var i=0; i < mem.length; i++){
var st = mem[i].getShape();
if(mem[i].optimise(that.canvas,transformation,projection)){
if(st == 'domElement')tran = transformation;
mem[i].render(that.canvas,tran,projection,true,that.settings.browser,ps);
if(mem[i].vmlfill && that.settings.globalAlpha) {
mem[i].vmlfill.opacity =that.settings.globalAlpha;
}
}
}
if(ctx)ctx.restore();
}
,render: function(args){
var projection = arguments[0];
if(this.settings.browser == 'good'){
this.canvas_render(projection);
}
else{
this.ie_render(projection);
}
}
,getTransformation: function(args){
if(!this.transformation) {
var ox = parseInt(this.canvas.style.width);
var oy = parseInt(this.canvas.style.height);
this.transformation = {scale:{x:1,y:1},translate:{x:0,y:0},origin:{x: ox/2, y: oy/2}};
//this.transformation = VismoTransformation.getBlankTransformation(this.canvas);
}
return this.transformation;
}
,setTransformation: function(args){
var transformation = arguments[0];
//console.log(transformation.origin.x,transformation.translate.x,transformation.translate.y);
if(!transformation.origin){
transformation.origin = {};
transformation.origin.x = jQuery(this.wrapper).width() / 2;
transformation.origin.y = jQuery(this.wrapper).height() / 2;
}
if(transformation) this.transformation = transformation;
var t = transformation.translate, s = transformation.scale;
transformation.cache = {id1:[s.x,",",s.y].join(""),id2:[t.x,",",t.y].join("")};
}
,centerOn: function(x,y){
var t= this.getTransformation();
t.translate.x = -x;
t.translate.y = -y;
if(this.vismoController){
this.vismoController.setTransformation(t);
}
else{
this.setTransformation(t);
}
this.render();
}
,remove: function(args){
var vismoShape = arguments[0];
var shapes = this.getMemory();
for(var i=0; i < shapes.length; i++){
if(shapes[i] == vismoShape){
this.memory.splice(i,1);
}
}
if(vismoShape.vml)vismoShape.vml.scrub();
var id = vismoShape.properties.id;
delete this._idtoshapemap[id]
}
,add: function(args){
var vismoShape = arguments[0];
this.needsSort = true;
if(!vismoShape._isVismoShape){
vismoShape = new VismoShape(vismoShape);
}
if(vismoShape.properties.shape =='point'){
vismoShape.setDimensions(this.options.pointsize,this.options.pointsize);
}
if(!this.memory) this.memory = [];
vismoShape.vismoCanvas = this;
if(!vismoShape.getProperty("id")){
var newid = this.memory.length +"_" + Math.random();
vismoShape.setProperty("id",newid);
}
vismoShape._canvasref = this._referenceid;
var id = vismoShape.properties.id;
this.memory.push(vismoShape);
this._idtoshapemap[id] = vismoShape;
vismoShape._vismoClickingID = id;
return vismoShape;
}
,addLabel:function(args){
var domElement = arguments[0];
var x= arguments[1];
var y = arguments[2];
this.labelHolder.appendChild(domElement);
var properties = {element: domElement,shape:"domElement"};
var coords = [];
coords.push(x);
coords.push(y);
var shape = new VismoShape(properties,coords);
this.add(shape);
//console.log(shape);
return {element: domElement ,vismoshape: shape};
}
,transform: function(args){
var t = arguments[0];
this.setTransformation(t);
this.render();
}
,clearMemory: function(args){
for(var i=0; i < this.memory.length; i++){
if(this.memory[i].vml){
this.memory[i].vml.scrub();
}
}
this._idtoshapemap = {};
this.memory = [];
},
getMemory: function(args){
if(this.needsSort){
this.memory =this.memory.sort(function(a,b){
var z1 = a.getProperty("z-index");
var z2 =b.getProperty("z-index");
if(z1 < z2) return -1;
else if(z1 == z2){
return 0;
}
else{
return 1;
}
});
this.needsSort = false;
}
return this.memory;
}
,getMemoryID: function(args){
var vismoShape = arguments[0];
if(vismoShape && vismoShape._vismoClickingID)
return vismoShape._vismoClickingID;
else{
return false;
}
}
,getShapeWithID: function(args){
var id = arguments[0];
var mem = this.getMemory();
if(this._idtoshapemap[id]) return this._idtoshapemap[id];
else return false;
}
,getShapeAtClick: function(args){
var e = arguments[0];
var el = arguments[1]; //the dom element the behaviour occurred o
if(!e) {
e = window.event;
}
var node = VismoClickingUtils.resolveTarget(e);
//alert(node.tagName);
if(node && node.tagName) { //vml vismoShape
if(node.tagName.toUpperCase() == 'SHAPE'){
if(node._vismoClickingID){
var shape = this.getShapeWithID(node._vismoClickingID);
if(shape) return shape;
}
}
}
var target = VismoClickingUtils.resolveTargetWithVismo(e);
target =el;
if(!target) return;
var offset = jQuery(target).offset();
var xy= VismoClickingUtils.scrollXY();
x = e.clientX + xy.x - offset.left;
y = e.clientY + xy.y - offset.top;
if(this.memory.length > 0){
var shape = false;
if(target.vismoClicking){
var pos = VismoTransformations.undoTransformation(x,y,this.transformation);
x = pos.x;
y = pos.y;
shape = this.getShapeAtPosition(x,y);
}
else{
//shape = false;
}
return shape;
} else{
return false;
}
},
getShapeAtPosition: function(args) {
/* x and y should be in VismoShape coordinate world*/
var x= arguments[0];
var y= arguments[1];
var shapes = this.memory;
var hitShapes = [];
for(var i=0; i < shapes.length; i++){
var shape = shapes[i];
if(!shape.getProperty("unclickable"))
{
var st = shape.getShape();
var g = shape.getBoundingBox();
if(x >= g.x1 && x <= g.x2 && y >= g.y1 && y <=g.y2){
hitShapes.push(shapes[i]);
}
}
}
if(hitShapes.length > 0){
var res = this._findNeedleInHaystack(x,y,hitShapes);
return res;
}
else return false;
// var shapesInsideBox = _findShapesInsideBoundingBox(shapes, ..) TODO RENAME
// var points = _findPointsInsideShapes(..)
},
_findNeedleInHaystack: function(args){
var x= arguments[0];
var y= arguments[1];
var shapes = arguments[2];
var hits = [];
for(var i=0; i < shapes.length; i++){
var st = shapes[i].getShape();
var itsahit = false;
if(st == 'polygon'){
itsahit = this._inPoly(x,y,shapes[i]);
}
else if(st == 'path'){
//itsahit = this._onPath(x,y,shapes[i]);
itsahit = false;
}
else if(st == 'image'){
itsahit = true;
}
else if(st == 'point' || st == 'circle'){
itsahit = this._inCircle(x,y,shapes[i]);
}
if(itsahit) {
hits.push(shapes[i]);
}
}
if(hits.length == 0){
return false;
}
else if(hits.length == 1)
return hits[0];
else {//the click is in a polygon which is inside another polygon
var bestZindex = {s:[],z:0};
for(var i=0; i < hits.length; i++){
var zin = hits[i].getProperty("z-index");
if(zin > bestZindex.z){
bestZindex.s = [hits[i]];
bestZindex.z = zin;
}
else if(zin == bestZindex.z){
bestZindex.s.push(hits[i]);
}
}
if(bestZindex.s.length == 1) return bestZindex.s[0];
var g = bestZindex.s[0].getBoundingBox();
var mindist = Math.min(g.x2 - x,x - g.x1,g.y2 - y,y - g.y1);
var closerEdge = {id:0, closeness:mindist};
for(var i=1; i < bestZindex.s.length; i++){
var g = bestZindex.s[i].getBoundingBox();
var mindist = Math.min(g.x2 - x,x - g.x1,g.y2 - y,y - g.y1);
if(closerEdge.closeness > mindist) {
closerEdge.id = i; closerEdge.closeness = mindist;
}
}
return bestZindex.s[closerEdge.id];
}
}
,_inCircle: function(args){
var x= arguments[0];
var y= arguments[1];
var vismoShape = arguments[2];
var bb = vismoShape.getBoundingBox();
var transform = vismoShape.getTransformation();
if(transform){
var newpos = VismoTransformations.applyTransformation(x,y,transform);
x= newpos.x;
y = newpos.y;
}
var a =((x - bb.center.x)*(x - bb.center.x)) + ((y - bb.center.y)*(y - bb.center.y));
var dim = vismoShape.getDimensions();
var w = dim.width;
var h = dim.height;
var inCircleOne;
var inCircleTwo;
if(transform && transform.scale) {
w *= transform.scale.x;
h *= transform.scale.y;
}
w *= w;
h *=h;
if (a <= w) inCircleOne= true;
else inCircleOne = false;
if (a <= h) inCircleTwo= true;
else inCircleTwo = false;
//console.log(bb.center.x,bb.center.y,x,y,vismoShape.properties.id,a,w,h,inCircleOne,inCircleTwo);
if(inCircleOne && inCircleTwo) return true;
else return false;
}
,_onPath: function(args){
var x= arguments[0];
var y= arguments[1];
var vismoShape = arguments[2];
return false;
}
,_inPoly: function(args) {
var x= arguments[0];
var y= arguments[1];
var vismoShape = arguments[2];
/* _inPoly adapted from inpoly.c
Copyright (c) 1995-1996 Galacticomm, Inc. Freeware source code.
http://www.visibone.com/inpoly/inpoly.c.txt */
var coords;
coords = vismoShape.getCoordinates();
var transform = vismoShape.getTransformation();
if(transform){
var newpos = VismoTransformations.applyTransformation(x,y,transform);
x = newpos.x;
y = newpos.y;
}
var npoints = coords.length;
if (npoints/2 < 3) {
//points don't describe a polygon
return false;
}
var inside = false;
var xold = coords[npoints-2];
var yold = coords[npoints-1];
var x1,x2,y1,y2,xnew,ynew;
for (var i=0; i<npoints; i+=2) {
xnew=coords[i];
ynew=coords[i+1];
if (xnew > xold) {
x1=xold;
x2=xnew;
y1=yold;
y2=ynew;
} else {
x1=xnew;
x2=xold;
y1=ynew;
y2=yold;
}
if ((xnew < x) == (x <= xold)
&& (y-y1)*(x2-x1) < (y2-y1)*(x-x1)) {
inside=!inside;
}
xold=xnew;
yold=ynew;
}
return inside;
}
,isOverlap: function(shape1,shape2){
return false;
}
};
var VismoCanvasRenderer = {
renderShape: function(canvas,vismoShape){
var ctx = canvas.getContext('2d');
var shapetype =vismoShape.properties.shape;
if(vismoShape.properties["lineWidth"]){
ctx.lineWidth = vismoShape.getProperty("lineWidth");
}
ctx.save();
ctx.beginPath();
if(shapetype == 'point' || shapetype =='circle'){
this.renderPoint(ctx,vismoShape);
}
else if(shapetype =='image'){
this.renderImage(ctx,vismoShape);
}
else if(shapetype == "path"){
this.renderPath(ctx,vismoShape);
}
else{
this.renderPath(ctx,vismoShape,true);
ctx.closePath();
}
ctx.strokeStyle = vismoShape.getProperty("stroke")
if(typeof vismoShape.getProperty("fill") == 'string')
fill = vismoShape.getProperty("fill");
else
fill = "#ffffff";
ctx.stroke();
if(shapetype != 'path') {
ctx.fillStyle = fill;
ctx.fill();
}
ctx.restore();
}
,renderPath: function(ctx,vismoShape,join){
var move = true,quadraticCurve = false,bezierCurve = false;
var c = vismoShape.getCoordinates();
var t =vismoShape.getProperty("transformation");
if(!t) t= {};
//ctx.save(); //issue with this in safari..
if(!t.translate)t.translate = {x:0,y:0};
if(!t.scale) t.scale = {x:1,y:1};
//ctx.scale(t.scale.x,t.scale.y);
if(!t.translate.y) t.translate.y = 0;
if(!t.translate.x) t.translate.x = 0;
if(!t.scale.x) t.scale.x = 1;
if(!t.scale.y) t.scale.y = 1;
var bb = vismoShape.grid;
if(bb.center){
ctx.translate(bb.center.x-(bb.center.x*t.scale.x),bb.center.y-(bb.center.y*t.scale.y));
ctx.scale(t.scale.x,t.scale.y);
ctx.translate(t.translate.x,t.translate.y);
}
var bb = vismoShape.grid;
for(var i=0; i < c.length-1; i+=2){
var isCoord =VismoShapeUtils._isCoordinate(c[i]);
if(!isCoord){
if(c[i] == "M"){
move=true;
}
else if(c[i] == "q"){
quadraticCurve = true;
}
else if(c[i] == "c"){
bezierCurve = true;
}
i+=1;
}
var x = parseFloat(c[i]);
var y = parseFloat(c[i+1]);
if(move){
ctx.moveTo(x,y);
move = false;
}
else if(quadraticCurve){
var x2 = parseFloat(c[i+2]);
var y2 = parseFloat(c[i+3]);
i+= 2;
ctx.quadraticCurveTo(x,y,x2,y2);
}
else if(bezierCurve){
var x2 = parseFloat(c[i+2]);
var y2 = parseFloat(c[i+3]);
var x3 = parseFloat(c[i+4]);
var y3 = parseFloat(c[i+5]);
i+= 4;
ctx.bezierCurveTo(x,y,x2,y2,x3,y3);
}
else{
ctx.lineTo(x,y);
}
}
//ctx.restore(); //issue with this in safari..
}
,renderPoint: function(ctx,vismoShape){
//ctx.restore();
//ctx.save();
var bb =vismoShape.getBoundingBox();
var dim =vismoShape.getDimensions();
var radiusx = dim.width / 2;
var radiusy = dim.height/2;
var transform = vismoShape.getTransformation();
if(transform && transform.scale) radiusx*= transform.scale.x;
//ctx.save();
if(radiusx > radiusy) {
//ctx.scale(radiusx/radiusy,1)
}
else if(radiusy > radiusx){
//
//ctx.scale(1,radiusy/radiusx)
//ctx.restore();
}
ctx.arc(bb.center.x, bb.center.y, radiusx, 0, Math.PI*2,true);
}
,renderImage: function(ctx,vismoShape){
var c = vismoShape.getCoordinates();
var bb = vismoShape.getBoundingBox();
var draw = function(){
if(vismoShape.ready)ctx.drawImage(vismoShape.image,bb.x1,bb.y1,bb.width,bb.height);
else window.setTimeout(draw,100);
};
draw();
}
};
var VismoGraph = function(properties){
this._nodes = {};
this._children = {};
this._parents = {};
this._orphans = {};
this._spouses = {};
if(properties.nodes){
for(var i=0; i < properties.nodes.length; i++){
this.addNode(properties.nodes[i]);
}
}
if(properties.edges){
var edges = properties.edges;
for(var i=0; i < edges.length; i++){
var a = edges[i][0];
var b = edges[i][1];
this.addEdge(a,b);
}
}
};
VismoGraph.prototype = {
getNode: function(id){
return this._nodes[id];
}
,depth: function(id,depthsofar){
if(!depthsofar && depthsofar !== 0)depthsofar =0;
var kids = this.getChildren(id);
if(kids.length == 0) return depthsofar;
var maxdepth = 0;
for(var i=0; i < kids.length;i++){
var depth = this.depth(kids[i],depthsofar+1)
if(depth > maxdepth) maxdepth = depth;
}
return maxdepth;
}
/* a spouse shares the same children as another node*/
,isSpouse: function(id1,id2){
if(id1 == id2) return false;
var childrenX = this.getChildren(id1);
var childrenY = this.getChildren(id2);
var allchildren = childrenX.concat(childrenY);
for(var i=0; i < allchildren.length; i++){
// if the child also has y as a parent..
var child = allchildren[0];
if(this._parents[child].indexOf(id2) != -1 && this._parents[child].indexOf(id1) != -1) return true;
}
return false;
}
,getSpouses: function(id){
var n = this.getNodes();
var spouses = [];
for(var i=0; i < n.length;i++){
if(this.isSpouse(id,n[i].id)){
spouses.push(n[i].id);
}
}
return spouses;
}
,getNodes: function(){
var nodes = [];
for(var i in this._nodes){
nodes.push(this._nodes[i]);
}
return nodes;
}
,getChildren: function(id){
if(typeof(id) != 'string'){
var done = {};
var allchildren = [];
for(var i=0; i < id.length;i++){
var parentid = id[i];
var children = this.getChildren(parentid);
for(var j=0; j < children.length;j++){
var childid = children[j];
if(!done[childid]){
allchildren.push(childid);
done[childid] = true;
}
}
}
return allchildren;
}
var children = this._children[id];
if(!children){
return [];
}
else {
return children;
}
}
,isOrphan: function(id){
if(!this._parents[id] || this._parents[id].length == 0){
return true;
}
else{
return false;
}
}
,getParents: function(id){
var p = this._parents[id];
if(!p){
return [];
}
else {
return p;
}
}
,getOrphans: function(){
var orphans = [];
var nodes = this.getNodes();
for(var i=0; i < nodes.length; i++){
var id = nodes[i].id;
if(this.isOrphan(id)){
orphans.push(id);
}
}
return orphans;
}
,addNode: function(nodejson){
var id = nodejson.id;
if(!nodejson.properties){
nodejson.properties = {};
}
this._nodes[id] = nodejson;
this._orphans[id] = true;
}
,addEdge: function(a,b){
if(!this._children[a]) this._children[a] = [];
if(!this._parents[b]) this._parents[b] = [];
this._children[a].push(b);
this._parents[b].push(a);
if(!this._orphans[a])this._orphans[a] = true;
this._orphans[b] = false;
}
};
var VismoGraphRenderer = function(place,options){
if(!options.algorithm){
throw "GraphRenderer requires an option called algorithm which is a function. This will take two parameters graph and root and should set XPosition and YPosition on every node.";
}
this.algorithm = options.algorithm;
if(!options.nodeWidth) options.nodeWidth= 5;
if(!options.nodeHeight) options.nodeHeight = 5;
this.options = options;
this._edgeShapeCoordinates = [];
this._graph = options.graph;
var canvasopts = {vismoController:{}};
if(options.move)canvasopts.move = options.move;
if(options.dblclick)canvasopts.dblclick = options.dblclick;
this._canvas = new VismoCanvas(place,canvasopts);
if(options.root){
this.compute(options.root);
}
};
VismoGraphRenderer.prototype = {
clear: function(){
this._canvas.clear(true);
this._edgeShapeCoordinates = [];
}
,compute: function(root){
var graph = this._graph;
if(this.options.root != root) this.clear();
if(root)this.options.root = root;
this.algorithm.compute(graph,this.options);
this.plot(root);
if(this._edgeShapeCoordinates.length > 0){
this._canvas.add(new VismoShape({shape:"path",coordinates:this._edgeShapeCoordinates}));
}
this._canvas.render();
var node = graph.getNode(root);
var half_height = this._canvas.height() /2;
this._canvas.centerOn(node.XPosition,node.YPosition + half_height);
}
,plot: function(id){
var node = this._graph.getNode(id);
var y = -node.YPosition;
var x = node.XPosition;
this.plotNode(id,{x:x,y:y});
var children = this._graph.getChildren(id);
for(var i=0; i < children.length; i++){
var parentpos = {x:x,y:y};
var ch =children[i];
var childxy = this.plot(ch);
if(parentpos && childxy){
this._edgeShapeCoordinates=this._edgeShapeCoordinates.concat(["M",parentpos.x,parentpos.y,childxy.x,childxy.y]);
}
}
return {x: x,y:y};
}
,plotNode: function(id,pos){
var exists = this._canvas.getShapeWithID(id);
if(!exists){
var st,coords;
st= "polygon";
var hr = this.options.nodeWidth /2;
var vr=this.options.nodeHeight /2;
coords = [pos.x-hr,pos.y-vr,pos.x+hr,pos.y-vr,pos.x+hr,pos.y+vr,pos.x-hr,pos.y+vr];
var node= this._graph.getNode(id);
node.properties.shape = st;
node.properties.coordinates = coords;
var shape= new VismoShape(node.properties);
this._canvas.add(shape);
}
else{
var b = exists.getBoundingBox();
pos = b.center;
}
return pos;
}
};var VismoVector = function(vismoShape,canvas){
VismoTimer.start("VismoVector.init");
this._iemultiplier = 10; //since vml doesn't accept floats you have to define the precision of your points 100 means you can get float coordinates 0.01 and 0.04 but not 0.015 and 0.042 etc..
this.vismoShape= vismoShape;
this.cache = {};
this.maxResolution_id_x = 1;
this._oldproperties = {};
this.initShape(vismoShape,canvas);
vismoShape.vml = this;
VismoTimer.end("VismoVector.init");
};
VismoVector.prototype = {
scrub: function(){
VismoTimer.start("VismoVector.scrub");
if(this.el){
this.el.parentNode.removeChild(this.el);
this.el = false;
}
VismoTimer.end("VismoVector.scrub");
}
,initShape: function(vismoShape,canvas){
VismoTimer.start("VismoVector.initShape");
this.coordinatesHaveChanged();
this.el = false;
var isVML;
var shapetype =vismoShape.properties.shape;
this.initialshapetype= shapetype;
if(shapetype == 'point' || shapetype == 'circle'){
this._initArc(vismoShape,canvas);
isVML = false;
}
else if(shapetype == 'image'){
this._initImage(vismoShape,canvas);
}
else if(shapetype == 'domElement'){
//this.haveAppended = true;
this.el = vismoShape.getProperty("element");
this.el.style.position = "absolute";
var el = this.el;
return;
}
else{
this._initPoly(vismoShape,canvas);
isVML = true;
}
if(isVML && canvas){
var w,h;
if(!canvas){
throw " i need a canvas to do my magic!";
}
if(canvas.width){
w= canvas.width;
}
else{
w = jQuery(canvas).width();
canvas.width = w;
}
if(canvas.height){
h= canvas.height;
}
else{
h = jQuery(canvas).height();
canvas.height= h;
}
var xspace = parseInt(w);
xspace *=this._iemultiplier;
var yspace =parseInt(h);
yspace *= this._iemultiplier;
coordsize = xspace +"," + yspace;
this.el.coordsize = coordsize;
}
if(this.vismoShape && this.el){
//this.el.vismoShape = this.vismoShape;
var nclass= "vismoShape";
if(shapetype == 'path'){ nclass= "vismoShapePath";}
this.el.setAttribute("class", nclass);
this.style();
}
var that= this;
//jQuery(window).bind("unload", function(){that.el= null;});
VismoTimer.end("VismoVector.initShape");
}
,_initImage: function(vismoShape,canvas){
var that = this;
var dim = vismoShape.getDimensions();
var setup = function(){
var shape = document.createElement("img");
that.el = shape;
shape.src = vismoShape.getProperty("src");
jQuery(shape).css({"height": dim.height, "width": dim.width,"position":"absolute","z-index":4});
};
var image = new Image();
image.src = vismoShape.getProperty("src");
image.onload = function(e){
setup();
};
if(image.complete){
setup();
}
}
,_initArc: function(vismoShape,canvas){
var shape = document.createElement("vismoShapeVml_:arc");
shape.startAngle = 0;
shape.endAngle = 360;
var bb = vismoShape.getBoundingBox();
this.el = shape;
var diameterx = bb.width;
var radiusx = bb.width/ 2;
var diametery = bb.height;
var radiusy= bb.height/ 2;
jQuery(this.el).css({"height": diametery, left:bb.center.x-radiusx, top: bb.center.y-radiusy,"width":diametery,"position":"absolute","z-index":4});
}
,_initPoly: function(vismoShape,canvas){
VismoTimer.start("VismoVector._initPoly");
var shape = document.createElement("vismoShapeVml_:shape");
this.el = shape;
this.el.name=vismoShape.properties.name;
//var css = jQuery(canvas).css();
var w =canvas.width;// css.width;
var h = canvas.height;//css.height;
jQuery(this.el).css({"height": h,"width": w,"position":"absolute","z-index":4});
VismoTimer.end("VismoVector._initPoly");
}
,getVMLElement: function(){
return this.el;
}
,_createvmlpathstring: function(transformation,projection){ //mr bottleneck
VismoTimer.start("VismoVector.createvmlpathstring");
var vml = this.el;
var o,t,s;
if(transformation){
o = transformation.origin;
t = transformation.translate;
s = transformation.scale;
}
else{
o = {x:0,y:0};
t = {x:0,y:0};
s = {x:1,y:1};
}
var cindex;
if(!s || (!s.x && !s.y)){
cindex = "1,1";
}else{
cindex= s.x+","+s.y;
}
if(!this.cache) {this.cache = {};}
if(!this.cache[cindex]){ this.cache[cindex] = {};}
if(!this.cache[cindex]["pathstring"]){
var path;
var buffer = [];
var c;
if(this.vismoShape.coordinates.normal){
c = this.vismoShape.coordinates.normal;
}
else{
c =this.vismoShape.getCoordinates("normal");
}
if(projection){
c = this.vismoShape._applyProjection(projection,transformation);
}
if(c.length < 2) return;
var x,y;
x = c[0];
y =c[1];
x *=this._iemultiplier;
y *= this._iemultiplier;
x = parseInt(x);
y = parseInt(y);
//path = "M";
buffer.push("M");
//path+= x + "," +y + " L";
buffer.push([x,",",y].join(""))
var lineTo = false,quadraticCurveTo = false,bezierCurveTo = false;
for(var i =2; i < c.length; i+=2){
if(c[i] == 'M') {
//path += " M";
buffer.push(" M");
lineTo = false;
i+=1;
}
else if(c[i] == 'z'){
buffer.push(" XE");
}
else if(c[i] == "q"){
quadraticCurveTo = true;
i += 1;
}
else if(c[i] == "c"){
bezierCurveTo = true;
i+=1;
}
else if(!lineTo) {
//path += " L";
buffer.push(" L");
lineTo = true;
}
else if(lineTo){
//path += " ";
buffer.push(" ");
}
var x =parseInt(c[i] * this._iemultiplier);
var y =parseInt(c[i+1] * this._iemultiplier);
if(quadraticCurveTo){
var x2 =parseInt(c[i+2] * this._iemultiplier);
var y2 =parseInt(c[i+3] * this._iemultiplier);
buffer.push([" c ",x,",",y,",",x2,",",y2,",",x2,",",y2,""].join(""));
i += 2;
quadraticCurveTo = false;
}
else if(bezierCurveTo){
var x2 =parseInt(c[i+2] * this._iemultiplier);
var y2 =parseInt(c[i+3] * this._iemultiplier);
var x3 = parseInt(c[i+4] * this._iemultiplier);
var y3 = parseInt(c[i+5] * this._iemultiplier);
buffer.push([" c ",x,",",y,",",x2,",",y2,",",x3,",",y3,""].join(""));
i += 4;
bezierCurveTo = false;
}
else{
buffer.push([x,",",y].join(""));
}
//path += x +"," + y;
//if(i < c.length - 2) path += "";
}
if(this.vismoShapeProperties.shape != "path"){buffer.push(" XE");}
this.cache[cindex]["pathstring"] = buffer.join("");
//console.log(buffer.join(""));
}
VismoTimer.end("VismoVector.createvmlpathstring");
return this.cache[cindex]["pathstring"];
}
,transformDomElement: function(transformation,projection){
VismoTimer.start("VismoVector.transformDomElement");
/*var o = transformation.origin, t = transformation.translate,s = transformation.scale;
*/
var shape = this.vismoShape;
var el = this.el;
var top,left,width,height;
var bb = shape.getBoundingBox();
dx = bb.x1;
dy = bb.y1;
jQuery(this.el).css({left:dx,top:dy});
VismoTimer.end("VismoVector.transformDomElement");
}
,coordinatesHaveChanged: function(){
this.coordinatesChanged = true;
}
,_cacheStyle: function(t,s,o){
VismoTimer.start("VismoVector._cacheStyle");
var vml = this.el;
if(!this.initialStyle) { //remember original placement
var initTop = parseInt(vml.style.top);
if(!initTop) initTop = 0;
var initLeft = parseInt(vml.style.left);
if(!initLeft) initLeft = 0;
var w =parseInt(vml.style.width);
var h = parseInt(vml.style.height)
this.initialStyle = {width: w, height: h};
}
var initialStyle= this.initialStyle;
var newwidth = initialStyle.width * s.x;
var newheight = initialStyle.height * s.y;
VismoTimer.end("VismoVector._cacheStyle");
return { width:newwidth+"px",height:newheight+"px"};
}
,_cssTransform: function(transformation,projection){
VismoTimer.start("VismoVector._cssTransform");
var vml = this.el;
var st = this.vismoShapeProperties.shape;
if(st == 'circle' || st == 'img' || st == 'domElement'){
this.transformDomElement(transformation,projection);
VismoTimer.end("VismoVector._cssTransform");
return;
}
if(!transformation) return;
var ckey_1, ckey_2;
if(transformation.cache){
ckey_1 = transformation.cache.id1;
ckey_2 = transformation.cache.id2;
}
else{
ckey_1 = "1,1";
ckey_2 = "0,0";
}
if(!this.cache[ckey_1]) this.cache[ckey_1] = {};
var s = transformation.scale;
if(!this.cache[ckey_1][ckey_2]){
var o = transformation.origin, t = transformation.translate;
this.cache[ckey_1][ckey_2] = this._cacheStyle(t,s,o);
}
var style = this.cache[ckey_1][ckey_2];
//jQuery(this.el).css(style); //jon
VismoTimer.end("VismoVector._cssTransform");
}
,clear: function(){
VismoTimer.start("VismoVector.clear");
var el = this.el;
try{
if(el)jQuery(el).css({display:"none"});
}catch(e){
};
VismoTimer.end("VismoVector.clear");
}
,render: function(canvas,transformation,projection){
VismoTimer.start("VismoVector.render");
var that = this;
var shape = this.el;
this.vismoShapeProperties = this.vismoShape.properties;
if(!shape){ //try again later
var f= function(){
that.render(canvas,transformation);
}
window.setTimeout(f,50);
return;
}
if(!this.haveAppended){ //append element to dom
shape._vismoClickingID = this.vismoShapeProperties.id;
}
if(this.coordinatesChanged) {
this._cssTransform(transformation,projection);
shape.path = this._createvmlpathstring(transformation,projection);//causes slow down..
this.coordinatesChanged = false;
}
var shtype= this.vismoShapeProperties.shape;
if(this.initialshapetype != shtype){ //shape type has changed force restart
this.scrub();
this.initShape(this.vismoShape,canvas);
this.haveAppended = false;
}
if(shtype!="domElement")shape.style.display = "";
if(!this.haveAppended){ //append element to dom
if(transformation)this._cssTransform(transformation,projection);
canvas.appendChild(shape);
if(shtype == 'domElement'){
var vismoShape = this.vismoShape;
var c = vismoShape.getCoordinates();
var rw = jQuery(el).width()/2;
var rh = jQuery(el).height()/2;
jQuery(el).css({position:"absolute",left:c[0],top:c[1]-rh});
}
this.haveAppended = true;
}
this.style();
VismoTimer.end("VismoVector.render");
}
,style: function(){
VismoTimer.start("VismoVector.style");
if(!this.vismoShapeProperties){
this.vismoShapeProperties = this.vismoShape.properties;
}
if(this.vismoShapeProperties.hidden){
jQuery(this.el).css({display:"none"});
}
if(this.nochange){
VismoTimer.end("VismoVector.style");
return;
}
jQuery("#log").append("Exiting");
this.nochange = true;
//if(this.el.className =='label')alert("!");
if(this.el.style.display == 'none') this.el.style.display =""
var shapetype = this.vismoShapeProperties.shape;
var shape = this.el;
shape.stroked = "t";
if(this.vismoShapeProperties["z-index"]){
shape.style.zIndex = this.vismoShapeProperties["z-index"];
}
if(this.vismoShapeProperties.lineWidth) {
shape.strokeweight =this.vismoShapeProperties.lineWidth + "em";
}
else {
shape.strokeweight = "1em";
}
var strokergba = this.vismoShapeProperties.stroke;
if(strokergba.indexOf("#") == 0 || strokergba.indexOf("rgb(") == 0){
shape.strokecolor = strokergba;
}
else{
if(!this.vmlstroke){
this.vmlstroke =document.createElement("vismoShapeVml_:stroke");
shape.appendChild(this.vmlstroke);
}
if(strokergba){
var stroke;
if(strokergba.indexOf("rgba") != -1 &&strokergba.match(/rgba\([0-9]*,[0-9]*,[0-9]*,(.*)\)/)){
var match =strokergba.match(/(rgb)a(\([0-9]*,[0-9]*,[0-9]*),(.*)\)/);
if(match[3]){
stroke = match[1] + match[2] +")";
this.vmlstroke.opacity = match[3];
}
}
else{
stroke = strokergba;
}
this.vmlstroke.color = stroke;
}
else{
this.vmlstroke.color = "rgb(0,0,0)";
}
}
if(!this.vismoShapeProperties["fill"] || shapetype == 'path'){
shape.filled = "f";
VismoTimer.end("VismoVector.style");
return;
}
var fill = this.vismoShapeProperties["fill"];
shape.filled = "t";
if(fill.indexOf("#") == 0 || fill.indexOf("rgb(") == 0){
shape.fillcolor = this.vismoShapeProperties.fill;
}
else{
if(!this.vmlfill && shape){
this.vmlfill =document.createElement("vismoShapeVml_:fill");
shape.appendChild(this.vmlfill);
}
//look for rgba fill for transparency
if(fill.indexOf("rgba") != -1 &&fill.match(/rgba\([0-9]*,[0-9]*,[0-9]*,(.*)\)/)){
var match =fill.match(/(rgb)a(\([0-9]*,[0-9]*,[0-9]*),(.*)\)/);
if(match[3]){
fill = match[1] + match[2] +")";
this.vmlfill.opacity = match[3];
}
}
this.vmlfill.color = fill;
}
this._oldproperties = VismoUtils.clone(this.vismoShapeProperties);
VismoTimer.end("VismoVector.style");
this.nochange = true;
}
};
var VismoTimer = {
startsAt:{},
timed: {},
clear: function(){
var i;
for(i in this.timed){
this.timed[i] = 0;
}
}
,start: function(id){
if(!this.timed[id]) this.timed[id] = 0;
this.startsAt[id] = new Date();
},
end: function(id){
var d = new Date();
this.timed[id] += (d-this.startsAt[id]);
},
summarise: function(selector){
var text ="";
for(i in this.timed){
text += i +": " + this.timed[i] .toString() +"\n";
}
jQuery(selector).val(text);
}
,blankf: function(){}
};
VismoTimer.start = VismoTimer.blankf;
VismoTimer.end = VismoTimer.blankf;
Creating spells under the Saga rules is left to the imagination of players and the discretion of the Narrator. A hero can attempt to create any magical effect using the schools and spheres he or she is familiar with. Remember, heroes cannot cast spells from schools and spheres they do not know.
Casting a spell is the same as any other hero action. The player declares what effect the hero will try to create, then plays a card from his or her hand to determine the spell's success. Using sorcery requires a Reason action, while wielding mysticism calls for a Spirit action. The Narrator assigns a difficulty rating to every spell. The more complex, intense, or long-lasting the spell effect, the harder it should be to cast. As a general rule, no spell should have a difficulty rating of less than 8.
Example: Ironhawk uses his skill in pyromancy to make his sword burn like a torch for ten minutes. The Narrator might decide this is an average Reason action. If Ironhawk wanted the sword to burn for thirty minutes, the action might become challenging. If, however, he wanted the torch to burn for an hour and work even while under water, the spell would likely be daunting or even more difficult.
Spells that target characters are always opposed actions unless the character is a willing subject of the spell or unable to resist. Sorcery is opposed by the target's Perception, while mysticism is resisted by the character's Presence.
A spell action is resolved like any other hero action. If the action score is equal to or higher than the difficulty rating (plus opposition ability score, where applicable), the spell succeeds. A failed action means the hero's spell simply doesn't work.
Spell points
Heroes cannot use magic indefinitely. Spells need energy to power them. That power comes in the form of spell points. Every time a spell action is attempted, the caster must spend a number of spell points equal to the difficulty rating of the spell. The caster must spend these spell points whether the spell succeeds or fails. If the hero doesn't have enough spell points to power a spell, it fails automatically, no matter how high an action score the player may generate.
Heroes begin each day with a full complement of spell points. They also recover spent spell points at a rate of 1 point per hour. Heroes who know both sorcery and mysticism recover 2 spell points per hour - 1 point for each discipline. Note: Reason spell points can be spent only on sorcery and Spirit spell points only on mysticism.
Resisting Magic
When a character tries to cast a spell at a hero, that hero's player may attempt an average Perception (Reason) action to resist sorcery, or an average Presence (Spirit) action to avoid mysticism.
Notes on Magic
Magic can be a challenge for players in a Saga game. It requires them to be creative and invent new and fantastic applications for their heroes' magical abilities. In the beginning, the Narrator may need to help players along, suggesting possible spells or helping them become familiar with the capabilities of the different schools and spheres. After a while, they will have a better feel for the magic system and become more innovative on their own.
Later, magic becomes problematic in a different way. In theory, a hero who knows the right schools (or spheres) and has the right cards can do almost anything in a scenario. However, magic is in the game to advance the story, not to allow the heroes to circumvent it. If the spells the heroes cast threaten to derail the story, the Narrator should invent a reason why they fail to work correctly. Do not over-use this power, but do not allow ultra-powerful magic to ruin a good story, either.
Entre los controles que se muestran al presionar {{{more}}}, los más relevantes son:
**{{{references}}}: muestra un listado de los micro-contenidos que enlazan hacia el que se está visualizando en ese momento.
**{{{jump}}}: despliega un listado de micro-contenidos relacionados, para saltar directamente a uno de ellos.
if(config.options.txtUserName != "OManzanilla") {
config.options.chkShowRightSidebar=false;
readOnly = true;
showBackstage = false;
}