]> git.llucax.com Git - z.facultad/75.07/algowars.git/blob - src/modelo/ov/Armas.pas
Import inicial después del "/var incident". :(
[z.facultad/75.07/algowars.git] / src / modelo / ov / Armas.pas
1 {** Contiene las armas que pueden ser usadas por las diferentes naves.<br>\r
2     <i>Cambios:</i>\r
3     <PRE>\r
4     10/11/00: Se agrega el manejo de excepciones para evitar un BUG en cMisilDirigido. Si el objetivo del misil\r
5               dirigido es destruido, la velocidad permanece constante y en mGetDebugInfo se informa que esta destruido.\r
6     27/11/00: Se le agrega el manejo de la velocidad maxima a la clase cArma y se agrega el Alcance del arma, cambiando\r
7               el anterior por la Duracion.\r
8     01/12/00: Se cambiaron las dimensiones de las armas para que los disparos sean mas "jugables".\r
9     </PRE>}\r
10 unit Armas;\r
11 \r
12 interface\r
13 \r
14 uses\r
15   Tipos,\r
16   Vectores,\r
17   ObjetoVolador;\r
18 \r
19 type\r
20   {** La clase cArma esta pensada como una clase abtracta. En ella se encuentran\r
21       características comunes a todas las armas.}\r
22   cArma = class( cObjetoVolador )\r
23     private\r
24       aDuracion:  tTiempo;   // Este alcance determina cuanto tiempo tiene que pasar\r
25                              //  para que el arma se autodestruya.\r
26       aAlcance:   tLongitud; // Alcance en metros del arma\r
27       aVelMaxima: tLongitud; // Velocidad máxima del arma\r
28     protected\r
29       {** Actualiza el alcance del arma, que va disminuyendo a medida que pasa el tiempo}\r
30       procedure mActualizarDuracion( dt: tTiempo );\r
31       {** Devuelve true si el arma todavia tiene alcance}\r
32       function mActivo: boolean;\r
33       {** Método para obtener el alcance del arma}\r
34       procedure mSetAlcance( alc: tLongitud );\r
35     public\r
36       {** Constructor}\r
37       constructor create( pos: cVector = nil; vel: cVector = nil; dim: tLongitud = 1;\r
38                           pot: tEnergia = 1; ene: tEnergia = 1; duracion: tTiempo = 2500;\r
39                           velMax: tLongitud = 0.25 ); overload;\r
40       {$IFDEF DebugAlgoWars}\r
41       {** Método heredado que devuelve un string con el estado del Objeto. Se utiliza para depurar\r
42           y la información entregada depende del parámetro tDebugInfo.}\r
43       function mGetDebugInfo( debugLevel: tDebugInfo = DI_MINI ): string; override;\r
44       {$ENDIF}\r
45       {** Método para obtener el alcance del arma}\r
46       function mGetAlcance: tLongitud;\r
47       {** Método para obtener el alcance del arma}\r
48       function mGetVelMax:  tLongitud;\r
49       {** Método heredado, se sobreescribe porque se le agrega alguna funcionalidad}\r
50       procedure mMover( dt: tTiempo ); override;\r
51       // SERIALIZACION\r
52       {** Devuelve una cadena de texto con el objeto serializado.}\r
53       function mSerializar: string; override;\r
54       {** Recrea el objeto a partir de una cadena de texto con el objeto\r
55           serializado.}\r
56       procedure mDesSerializar( str: string ); override;\r
57   end;\r
58 \r
59   {** El laser es un tipo de arma básica. Es la que menos daño hace pero la que más rápido viaja<br>\r
60       <u>Características:</u>\r
61       <PRE>\r
62       Dimensión      0,1       metros (10 cm)\r
63       Potencia:      1         Cantidad de daño que hace por intervalo de tiempo\r
64       Energía:       1         Cantidad de daño que soporta antes de ser destruída\r
65       Velocidad:     0,4       metros/milisegundos (1440 km/h)\r
66       Alcance:       3000      milisegundos (3 segundos, 1,2 km)\r
67       </PRE>}\r
68   cLaser = class( cArma )\r
69     public\r
70       {** Constructor}\r
71       constructor create( pos: cVector = nil; vel: cVector = nil ); overload;\r
72       {** Método heredado, se sobreescribe porque se dibuja de forma distinta}\r
73       function mDibujar: tObjetosVoladores; override;\r
74   end;\r
75 \r
76   {** El misil es un tipo de arma básica. Hace un daño considerable y su velocidad también es alta<br>\r
77       <u>Características:</u>\r
78       <PRE>\r
79       Dimensión      0,5       metros (50 cm)\r
80       Potencia:      20        Cantidad de daño que hace por intervalo de tiempo\r
81       Energía:       1         Cantidad de daño que soporta antes de ser destruída\r
82       Velocidad:     0,3       metros/milisegundos (1080 km/h)\r
83       Alcance:       5000      milisegundos (5 segundos, 1,5 km)\r
84       </PRE>}\r
85   cMisil = class( cArma )\r
86     public\r
87       // Constructor\r
88       constructor create( pos: cVector = nil; vel: cVector = nil ); overload;\r
89       // Método heredado, se sobreescribe porque se dibuja de forma distinta\r
90       function mDibujar: tObjetosVoladores; override;\r
91   end;\r
92 \r
93   {** El misil dirigido es un tipo de arma avanzada. Persigue a su objetivo hasta que lo alcanza o\r
94       hasta que se le acaba el alcance. Hace un daño alto, su velocidad es mediana y tiene un gran alcance.<br>\r
95       <u>Características:</u>\r
96       <PRE>\r
97       Dimensión      0,7       metros (70 cm)\r
98       Potencia:      30        Cantidad de daño que hace por intervalo de tiempo\r
99       Energía:       1         Cantidad de daño que soporta antes de ser destruída\r
100       Velocidad:     0,25      metros/milisegundos (900 km/h)\r
101       Alcance:       20000     milisegundos (20 segundos, 5 km)\r
102       Area de Lock:  2000      metros (2 km)\r
103       </PRE>}\r
104   cMisilDirigido = class( cMisil )\r
105     private\r
106       aObjetivo:  cObjetoVolador;      // Objetivo del misil\r
107       aLockArea:  tLongitud;           // Maxima distancia a la que se debe encontrar\r
108                                        //  el objetivo para poder ser disparado\r
109     protected\r
110       {** Método que calcula la nueva velocidad basandose en al posicion del objetivo}\r
111       procedure mModificarVelocidad;\r
112     public\r
113       {** Constructor}\r
114       constructor create( obj: cObjetoVolador; pos: cVector = nil ); overload;\r
115       {$IFDEF DebugAlgoWars}\r
116       {** Método heredado que devuelve un string con el estado del Objeto. Se utiliza para depurar\r
117           y la información entregada depende del parámetro tDebugInfo.}\r
118       function mGetDebugInfo( debugLevel: tDebugInfo = DI_MINI ): string; override;\r
119       {$ENDIF}\r
120       {** Método heredado, se sobreescribe porque se le agrega alguna funcionalidad}\r
121       procedure mMover( dt: tTiempo ); override;\r
122       {** Obtiene el objetivo del misil dirigido}\r
123       function mGetObjetivo: cObjetoVolador;\r
124       {** Establece el objetivo del misil dirigido}\r
125       procedure mSetObjetivo( ov: cObjetoVolador );\r
126       {** Método heredado, se sobreescribe porque se dibuja de forma distinta}\r
127       function mDibujar: tObjetosVoladores; override;\r
128       // SERIALIZACION\r
129       {** Devuelve una cadena de texto con el objeto serializado.}\r
130       function mSerializar: string; override;\r
131       {** Recrea el objeto a partir de una cadena de texto con el objeto\r
132           serializado.}\r
133       procedure mDesSerializar( str: string ); override;\r
134   end;\r
135 \r
136 implementation\r
137 \r
138 uses\r
139   RegExpr,\r
140   ObjetoPersistente,\r
141   SerializacionUtils,\r
142   Sysutils;\r
143 \r
144 { cArma }\r
145 \r
146 {** Este constructor es protegido porque solo va a ser utilizado por subclases\r
147     @param pos     Posicion inicial\r
148     @param vel     Velocidad inicial\r
149     @param dim     Dimensión del objeto volador (radio, en metros)\r
150     @param pot     Potencia del objeto volador (cantidad de daño que hace por intervalode tiempo)\r
151     @param ene     Energía del objeto volador(cantidad de daño que soporta antes de ser destruido)\r
152     @param alcance Tiempo que debe pasar para que el arma se destruya si no impactó con ningún objeto volador}\r
153 constructor cArma.create(pos: cVector; vel: cVector; dim: tLongitud;\r
154   pot, ene: tEnergia; duracion: tTiempo; velMax: tLongitud);\r
155 var\r
156   v: cVector;\r
157 begin\r
158   inherited create( pos, vel, dim, pot, ene );\r
159   aDuracion  := duracion;\r
160   aVelMaxima := velMax;\r
161   aAlcance   := aDuracion * aVelMaxima;\r
162   // Setea el modulo de la velocidad a la maxima\r
163   v := mGetVelocidad.mSetModulo( aVelMaxima );\r
164   mSetVelocidad( v );\r
165   v.free;\r
166 end;\r
167 \r
168 {** Chequea si el arma todavia tiene alcance\r
169     @return <i>true</i> si todavía tiene alcance, <i>false</i> si no}\r
170 function cArma.mActivo: boolean;\r
171 begin\r
172   result := ( aDuracion > 0 );\r
173 end;\r
174 \r
175 {** Método para obtener el alcance del arma\r
176     @return Alcance del arma}\r
177 function cArma.mGetAlcance: tLongitud;\r
178 begin\r
179   result := aAlcance;\r
180 end;\r
181 \r
182 {** Método para establecer el alcance del arma\r
183     @param alc Alcance del arma}\r
184 procedure cArma.mSetAlcance(alc: tLongitud);\r
185 begin\r
186   aAlcance := alc;\r
187 end;\r
188 \r
189 {** Método para obtener la velocidad maxima del arma\r
190     @return Velocidad maxima del arma}\r
191 function cArma.mGetVelMax: tLongitud;\r
192 begin\r
193   result := aVelMaxima;\r
194 end;\r
195 \r
196 {** Actualiza el alcance del arma, que va disminuyendo a medida que pasa el tiempo\r
197     @param dt Intervalo de tiempo}\r
198 procedure cArma.mActualizarDuracion(dt: tTiempo);\r
199 begin\r
200   aDuracion := aDuracion - dt;\r
201 end;\r
202 \r
203 {$IFDEF DebugAlgoWars}\r
204 {** Devuelve el estado del objeto basandose en la cantidad de datos requeridos.\r
205     @return            Cadena de texto con el estado del Objeto.\r
206     @param   debugLevel Cantidad de información requerida}\r
207 function cArma.mGetDebugInfo(debugLevel: tDebugInfo): string;\r
208 begin\r
209   // Genera el string con el estado del Arma\r
210   result := inherited mGetDebugInfo( debugLevel );\r
211   if debugLevel > DI_MINI then\r
212     result := result + ' | Alcance: ' + FloatToStr( aDuracion );\r
213 end;\r
214 {$ENDIF}\r
215 \r
216 {** Mueve el arma basado en su posición y velocidad actual y un intervalo de tiempo\r
217     @param dt Intervalo de tiempo}\r
218 procedure cArma.mMover(dt: tTiempo);\r
219 begin\r
220   inherited mMover( dt );  // Mueve el arma de la forma convencional\r
221   mActualizarDuracion( dt ); // Actualiza el alcance\r
222   if not mActivo then // Si se quedó sin alcance...\r
223     mSetEnergia( -1 ); // pone energia en negativo, lo que significa que se destruyó...\r
224 end;\r
225 \r
226 {** Recrea el objeto a partir de una cadena de texto con el objeto\r
227     serializado.\r
228     @param str Cadena de texto con el objeto serializado.}\r
229 procedure cArma.mDesSerializar(str: string);\r
230 var\r
231   r: TRegExpr;\r
232 begin\r
233   inherited mDesSerializar( str ); // SIEMPRE el ID debe ser el PRIMER atributo\r
234   r := TRegExpr.create;\r
235   // DURACION\r
236   try // se fija si hay errores al extraer los datos\r
237     r.Expression := '<duracion>\s*([+-]?\d+)\s*</duracion>'; // contruye la expresion regular a buscar\r
238     if r.Exec ( str ) then // Ejecuta la expresion. Si la encuentra...\r
239       aDuracion := StrToFloat( r.Match[1] )\r
240     else // si no encontro la experesion...\r
241       raise ESerializacion.create( 'No se encontro la duracion' ); // cae en una excepcion\r
242   except // Si hubieron errores ...\r
243     on e: ERegExpr do begin // si fueron de expresiones regulares...\r
244       r.Free; // libera memoria\r
245       raise ESerializacion.create( ClassName + ': Error al extraer la duracion utilizando expresiones regulares: ' + e.Message ); // cae en una excepcion\r
246     end;\r
247   end;\r
248   // ALCANCE\r
249   try // se fija si hay errores al extraer los datos\r
250     r.Expression := '<alcance>\s*([+\-]?\d+(\,\d+)?([eE][+\-]?\d+)?)\s*</alcance>'; // contruye la expresion regular a buscar\r
251     if r.Exec ( str ) then // Ejecuta la expresion. Si la encuentra...\r
252       aAlcance := StrToFloat( r.Match[1] )\r
253     else // si no encontro la experesion...\r
254       raise ESerializacion.create( 'No se encontro el alcance' ); // cae en una excepcion\r
255   except // Si hubieron errores ...\r
256     on e: ERegExpr do begin // si fueron de expresiones regulares...\r
257       r.Free; // libera memoria\r
258       raise ESerializacion.create( ClassName + ': Error al extraer el alcance utilizando expresiones regulares: ' + e.Message ); // cae en una excepcion\r
259     end;\r
260   end;\r
261   // VELMAXIMA\r
262   try // se fija si hay errores al extraer los datos\r
263     r.Expression := '<velmaxima>\s*([+\-]?\d+(\,\d+)?([eE][+\-]?\d+)?)\s*</velmaxima>'; // contruye la expresion regular a buscar\r
264     if r.Exec ( str ) then // Ejecuta la expresion. Si la encuentra...\r
265       aVelMaxima := StrToFloat( r.Match[1] )\r
266     else // si no encontro la experesion...\r
267       raise ESerializacion.create( 'No se encontro la velocidad maxima' ); // cae en una excepcion\r
268   except // Si hubieron errores ...\r
269     on e: ERegExpr do begin // si fueron de expresiones regulares...\r
270       r.Free; // libera memoria\r
271       raise ESerializacion.create( ClassName + ': Error al extraer la velocidad maxima utilizando expresiones regulares: ' + e.Message ); // cae en una excepcion\r
272     end;\r
273   end;\r
274   r.free;\r
275 end;\r
276 \r
277 {** Devuelve una cadena de texto con el objeto serializado.\r
278     @return Cadena de texto con el objeto serializado.}\r
279 function cArma.mSerializar: string;\r
280 begin\r
281   result := inherited mSerializar +\r
282             '<duracion>' + FloatToStrF( aDuracion, ffGeneral, 18, 0 ) + '</duracion>' +\r
283             '<alcance>' + FloatToStrF( aAlcance, ffGeneral, 18, 0 ) + '</alcance>' +\r
284             '<velmaxima>' + FloatToStrF( aVelMaxima, ffGeneral, 18, 0 ) + '</velmaxima>';\r
285 end;\r
286 \r
287 { cLaser }\r
288 \r
289 {** Crea una nueva instancia.\r
290     @param pos Vector posición\r
291     @param vel Dirección del vector velocidad}\r
292 constructor cLaser.create(pos: cVector = nil; vel: cVector = nil);\r
293 begin\r
294   // El laser tiene 10 cm de radio, 1 punto de potencia, 1 punto de energia y 3 seg de alcance (1,2 km)\r
295   // Setea el modulo de la velocidad a 0,4 m/mseg (1440 km/h)\r
296   inherited create( pos, vel, 0.1 {dim}, 1 {pot}, 1 {ene}, 3000 {dur}, 0.4 {velmax} );\r
297 end;\r
298 \r
299 {** Método heredado, se sobreescribe porque se dibuja de forma distinta}\r
300 function cLaser.mDibujar: tObjetosVoladores;\r
301 begin\r
302   result := OV_LASER;\r
303 end;\r
304 \r
305 { cMisil }\r
306 \r
307 {** Crea una nueva instancia.\r
308     @param pos Vector posición\r
309     @param vel Dirección del vector velocidad}\r
310 constructor cMisil.create(pos: cVector = nil; vel: cVector = nil);\r
311 begin\r
312   // El misil tiene 50 cm de radio, 20 puntos de potencia, 1 punto de energia y 5 seg de alcance (1,5 km)\r
313   // Setea el modulo de la velocidad a 0,3 m/mseg (1080 km/h)\r
314   inherited create( pos, vel, 0.5 {dim}, 20 {pot}, 1 {ene}, 5000 {dur}, 0.3 {velmax} );\r
315 end;\r
316 \r
317 {** Método heredado, se sobreescribe porque se dibuja de forma distinta}\r
318 function cMisil.mDibujar: tObjetosVoladores;\r
319 begin\r
320   result := OV_MISIL;\r
321 end;\r
322 \r
323 { cMisilDirigido }\r
324 \r
325 {** Crea una nueva instancia.\r
326     @param obj Objeto volador al que perseguirá (objetivo)\r
327     @param pos Vector posición}\r
328 constructor cMisilDirigido.create( obj: cObjetoVolador; pos: cVector = nil );\r
329 begin\r
330   // El misil dirigido tiene 70 m de radio, 30 puntos de potencia, 1 punto de energia y 20 seg de alcance (5 km)\r
331   inherited create( pos, cVector.create, 0.7 {dim}, 30 {pot}, 1 {ene}, 20000 {dur}, 0.25 {velmax} );\r
332   aObjetivo := obj;\r
333   aLockArea := 2000;   // 2 km\r
334   mSetAlcance( aLockArea ); // Setea como alcance al area de lockeo.\r
335   mModificarVelocidad; // Modifica la velocidad de forma tal que apunte al objetivo\r
336                        //  y tenga un modulo constante\r
337 end;\r
338 \r
339 {** Método que calcula la nueva velocidad basandose en al posicion del objetivo}\r
340 procedure cMisilDirigido.mModificarVelocidad;\r
341 var\r
342   pos,           // Vector temporal para hacer calculos\r
343   vel: cVector;  // Vector temporal para hacer calculos\r
344 begin\r
345   vel := nil;\r
346   pos := nil;\r
347   if aObjetivo <> nil then // Si no es nulo ...\r
348     try // Probamos que el objetivo no este destruido\r
349       // Le resta la posicion propia a la del objetivo, obteniendo la nueva direccion de la velocidad\r
350       pos := mGetPosicion;\r
351       vel := aObjetivo.mGetPosicion.mRestar( pos );\r
352       vel.mSetModulo( mGetVelMax ); // Setea el modulo al de la velocidad maxima: 0,25 m/mseg (900 km/h)\r
353       mSetVelocidad( vel ); // Modifica la velocidad basado en el vector v\r
354     except // Si esta destruido queda la velocidad constante y libera los vectores\r
355       on e: EAccessViolation do begin\r
356         mSetVelModulo( mGetVelMax ); // Setea el modulo de la velocidad como la maxima\r
357                                      // (no cambia su direccion ni sentido)\r
358         aObjetivo := nil; // Lo seteamos a nil\r
359         vel.free; // libera la memoria del vector temporal\r
360         pos.free; // libera la memoria del vector temporal\r
361       end;\r
362     end;\r
363   // Si es nulo no modifica la velocidad ...\r
364 end;\r
365 \r
366 {** Mueve el arma basado en su posición y velocidad actual, su objetivo y un intervalo de tiempo\r
367     @param dt Intervalo de tiempo}\r
368 procedure cMisilDirigido.mMover(dt: tTiempo);\r
369 begin\r
370   mModificarVelocidad;    // Modifica la velocidad segun su objetivo\r
371   inherited mMover( dt ); // Se mueve al igual que el resto de las armas\r
372 end;\r
373 \r
374 {$IFDEF DebugAlgoWars}\r
375 {** Devuelve el estado del objeto basandose en la cantidad de datos requeridos.\r
376     @return            Cadena de texto con el estado del Objeto.\r
377     @param   debugLevel Cantidad de información requerida}\r
378 function cMisilDirigido.mGetDebugInfo(debugLevel: tDebugInfo): string;\r
379 var\r
380   objInfo: string;\r
381 begin\r
382   // Genera el string con el estado del Misil Dirigido\r
383   result := inherited mGetDebugInfo( debugLevel );\r
384   if debugLevel > DI_MINI then\r
385     result := result + ' | LockArea: ' + FloatToStr( aLockArea );\r
386   if aObjetivo <> nil then // Si no es nulo ...\r
387     try // Probamos que el objetivo no este destruido\r
388       objInfo := aObjetivo.mGetDebugInfo( DI_MINI );\r
389     except // Si esta destruido cambia la cadena de texto\r
390       on e: EAccessViolation do begin\r
391         objInfo := 'DESTRUIDO';\r
392         aObjetivo := nil;\r
393       end;\r
394     end\r
395   else // Si es nulo ...\r
396     objInfo := 'DESTRUIDO';\r
397   if debugLevel > DI_NORMAL then\r
398     result := result + #13 + #10 + 'Objetivo: ' + objInfo;\r
399 end;\r
400 {$ENDIF}\r
401 \r
402 {** Obtiene el objetivo del misil dirigido.\r
403     @return Objetivo del misil dirigido.}\r
404 function cMisilDirigido.mGetObjetivo: cObjetoVolador;\r
405 begin\r
406   result := aObjetivo;\r
407   if aObjetivo <> nil then // Si no es nil...\r
408     try // Primero se fija que no esté destruido\r
409       aObjetivo.mGetID;\r
410     except\r
411       on e: EAccessViolation do begin // Si lo está...\r
412         aObjetivo := nil; // Lo setea a nil\r
413         result := aObjetivo;\r
414       end;\r
415     end;\r
416 end;\r
417 \r
418 {** Establece el objetivo del misil dirigido\r
419     @param ov Nuevo objetivo}\r
420 procedure cMisilDirigido.mSetObjetivo( ov: cObjetoVolador );\r
421 begin\r
422   aObjetivo := ov;\r
423 end;\r
424 \r
425 {** Método heredado, se sobreescribe porque se dibuja de forma distinta}\r
426 function cMisilDirigido.mDibujar: tObjetosVoladores;\r
427 begin\r
428     result := OV_MISDIR;\r
429 end;\r
430 \r
431 {** Recrea el objeto a partir de una cadena de texto con el objeto\r
432     serializado.\r
433     @param str Cadena de texto con el objeto serializado.}\r
434 procedure cMisilDirigido.mDesSerializar(str: string);\r
435 var\r
436   r: TRegExpr;\r
437 begin\r
438   inherited mDesSerializar( str ); // SIEMPRE el ID debe ser el PRIMER atributo\r
439   r := TRegExpr.create;\r
440   // OBJETIVO\r
441   try // se fija si hay errores al extraer los datos\r
442     r.Expression := '<objetivo\s+class=([\w\d]+)\s*>\s*(.+)\s*</objetivo>'; // contruye la expresion regular a buscar\r
443     if r.Exec ( str ) then // Ejecuta la expresion. Si la encuentra...\r
444       if r.Match[1] <> '0' then // Si tiene una clase determinada...\r
445         if aObjetivo <> nil then // Si no es nulo\r
446           // Puede caer en una EAccessViolation si esta destruido\r
447           aObjetivo.mDesSerializar( r.Match[2] ) // Lo deserializa\r
448         else // si es nulo\r
449           aObjetivo := restaurarObjeto( r.Match[1], r.Match[2] ) // lo crea segun su clase\r
450       else // Si no tiene una clase determinada, entonces se lo pone en nil\r
451         aObjetivo := nil\r
452     else // si no encontro la experesion...\r
453       raise ESerializacion.create( 'No se encontro el objetivo' ); // cae en una excepcion\r
454   except // Si hubieron errores ...\r
455     on e: ESerializacion do begin // Si fueron de serializacion...\r
456       r.Free; // libera memoria\r
457       raise ESerializacion.create( ClassName + ': Error al deserializar el objetivo: ' + e.Message ); // cae en una excepcion\r
458     end;\r
459     on e: ERegExpr do begin // si fueron de expresiones regulares...\r
460       r.Free; // libera memoria\r
461       raise ESerializacion.create( ClassName + ': Error al extraer el objetivo utilizando expresiones regulares: ' + e.Message ); // cae en una excepcion\r
462     end;\r
463     on e: EAccessViolation do begin // si el Objetivo fue destruido...\r
464       aObjetivo := restaurarObjeto( r.Match[1], r.Match[2] ) // lo crea segun su clase\r
465     end;\r
466   end;\r
467   // LOCKAREA\r
468   try // se fija si hay errores al extraer los datos\r
469     r.Expression := '<lockarea>\s*([+\-]?\d+(\,\d+)?([eE][+\-]?\d+)?)\s*</lockarea>'; // contruye la expresion regular a buscar\r
470     if r.Exec ( str ) then // Ejecuta la expresion. Si la encuentra...\r
471       aLockArea := StrToFloat( r.Match[1] )\r
472     else // si no encontro la experesion...\r
473       raise ESerializacion.create( 'No se encontro el area de lockeo' ); // cae en una excepcion\r
474   except // Si hubieron errores ...\r
475     on e: ERegExpr do begin // si fueron de expresiones regulares...\r
476       r.Free; // libera memoria\r
477       raise ESerializacion.create( ClassName + ': Error al extraer el area de lockeo utilizando expresiones regulares: ' + e.Message ); // cae en una excepcion\r
478     end;\r
479   end;\r
480   r.free;\r
481 end;\r
482 \r
483 {** Devuelve una cadena de texto con el objeto serializado.\r
484     @return Cadena de texto con el objeto serializado.}\r
485 function cMisilDirigido.mSerializar: string;\r
486 var\r
487   clase,\r
488   objetivo: string;\r
489 begin\r
490   // Si el objetivo es nil o está destruido, se setea el atributo class del\r
491   // TAG objetivo como '0' y entre el TAG se indica que es nil. Si no se\r
492   // setea como el nombre de la clase y su expresion serializada respectivamente\r
493   objetivo := 'nil';\r
494   clase    := '0';\r
495   if aObjetivo <> nil then\r
496     try\r
497       objetivo := aObjetivo.mSerializar;\r
498       clase    := aObjetivo.ClassName;\r
499     except // Si esta destruido cambia la cadena de texto\r
500       on e: EAccessViolation do begin\r
501         objetivo := 'nil';\r
502         clase    := '0';\r
503         aObjetivo := nil;\r
504       end;\r
505     end;\r
506   result := inherited mSerializar +\r
507             '<objetivo class=' + clase + '>' + objetivo + '</objetivo>' +\r
508             '<lockarea>' + FloatToStrF( aLockArea, ffGeneral, 18, 0 ) + '</lockarea>';\r
509 end;\r
510 \r
511 end.\r