1 /*
2 * Copyright 2011-2012 Arx Libertatis Team (see the AUTHORS file)
3 *
4 * This file is part of Arx Libertatis.
5 *
6 * Arx Libertatis is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * Arx Libertatis is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with Arx Libertatis. If not, see <http://www.gnu.org/licenses/>.
18 */
19 /* Based on:
20 ===========================================================================
21 ARX FATALIS GPL Source Code
22 Copyright (C) 1999-2010 Arkane Studios SA, a ZeniMax Media company.
23
24 This file is part of the Arx Fatalis GPL Source Code ('Arx Fatalis Source Code').
25
26 Arx Fatalis Source Code is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
27 License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
28
29 Arx Fatalis Source Code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
30 warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
31
32 You should have received a copy of the GNU General Public License along with Arx Fatalis Source Code. If not, see
33 <http://www.gnu.org/licenses/>.
34
35 In addition, the Arx Fatalis Source Code is also subject to certain additional terms. You should have received a copy of these
36 additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Arx
37 Fatalis Source Code. If not, please request a copy in writing from Arkane Studios at the address below.
38
39 If you have questions concerning this license or the applicable additional terms, you may contact in writing Arkane Studios, c/o
40 ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
41 ===========================================================================
42 */
43 // Copyright (c) 1999-2001 ARKANE Studios SA. All rights reserved
44
45 #include "graphics/spells/Spells07.h"
46
47 #include "animation/AnimationRender.h"
48
49 #include "core/GameTime.h"
50
51 #include "game/Damage.h"
52 #include "game/EntityManager.h"
53 #include "game/Player.h"
54 #include "game/Spells.h"
55
56 #include "graphics/Math.h"
57 #include "graphics/data/TextureContainer.h"
58 #include "graphics/effects/SpellEffects.h"
59 #include "graphics/particle/ParticleEffects.h"
60 #include "graphics/particle/ParticleParams.h"
61 #include "graphics/spells/Spells05.h"
62
63 #include "physics/Collisions.h"
64
65 #include "scene/Object.h"
66 #include "scene/Interactive.h"
67 #include "scene/Light.h"
68
69 struct CLightning::LIGHTNING {
70 Vec3f eStart;
71 Vec3f eVect;
72 int anb;
73 int anbrec;
74 bool abFollow;
75 int aParent;
76 float fAngleXMin;
77 float fAngleXMax;
78 float fAngleYMin;
79 float fAngleYMax;
80 float fAngleZMin;
81 float fAngleZMax;
82 };
83
84 //------------------------------------------------------------------------------
CLightning()85 CLightning::CLightning() :
86 nbtotal(0),
87 lNbSegments(40),
88 invNbSegments(1.0f / 40.0f),
89 fSize(100.0f),
90 fLengthMin(5.0f),
91 fLengthMax(40.0f),
92 fAngleXMin(5.0f),
93 fAngleXMax(32.0f),
94 fAngleYMin(5.0f),
95 fAngleYMax(32.0f),
96 fAngleZMin(5.0f),
97 fAngleZMax(32.0f),
98 falpha(1.0f),
99 fDamage(1)
100 {
101 SetDuration(2000);
102 ulCurrentTime = ulDuration + 1;
103
104 SetColor1(1.0f, 1.0f, 1.0f);
105 SetColor2(0.0f, 0.0f, 0.2f);
106
107 tex_light = NULL;
108 }
109
110 //------------------------------------------------------------------------------
111 // Params une méchante struct
112 //------------------------------------------------------------------------------
113
BuildS(LIGHTNING * pLInfo)114 void CLightning::BuildS(LIGHTNING * pLInfo)
115 {
116 Vec3f astart = pLInfo->eStart;
117 Vec3f avect = pLInfo->eVect;
118
119 if ((pLInfo->anb > 0) && (nbtotal < 2000))
120 {
121 nbtotal++;
122 int moi = nbtotal;
123
124 if(pLInfo->abFollow) {
125 avect = (eDest - pLInfo->eStart).getNormalized();
126 }
127
128 float fAngleX = frand2() * (pLInfo->fAngleXMax - pLInfo->fAngleXMin) + pLInfo->fAngleXMin;
129 float fAngleY = frand2() * (pLInfo->fAngleYMax - pLInfo->fAngleYMin) + pLInfo->fAngleYMin;
130 float fAngleZ = frand2() * (pLInfo->fAngleZMax - pLInfo->fAngleZMin) + pLInfo->fAngleZMin;
131
132 Vec3f av;
133 av.x = (float) cos(acos(avect.x) - radians(fAngleX));
134 av.y = (float) sin(asin(avect.y) - radians(fAngleY));
135 av.z = (float) tan(atan(avect.z) - radians(fAngleZ));
136 av.normalize();
137 avect = av;
138
139 float ts = rnd();
140 av *= ts * (fLengthMax - fLengthMin) * pLInfo->anb * invNbSegments + fLengthMin;
141
142 astart += av;
143 pLInfo->eStart = astart;
144
145 cnodetab[nbtotal].pos = pLInfo->eStart;
146 cnodetab[nbtotal].size = cnodetab[0].size * pLInfo->anb * invNbSegments;
147 cnodetab[nbtotal].parent = pLInfo->aParent;
148
149 int anb = pLInfo->anb;
150 int anbrec = pLInfo->anbrec;
151
152 float p = rnd();
153
154 if ((p <= 0.15) && (pLInfo->anbrec < 7))
155 {
156 float m = rnd();
157
158 if (pLInfo->abFollow)
159 {
160 pLInfo->eStart = astart;
161 pLInfo->eVect = avect;
162 pLInfo->abFollow = false;
163 pLInfo->anb = anb - (int)(10 * (1 - m));
164 pLInfo->anbrec = anbrec + (int)(2 * m);
165 pLInfo->aParent = moi;
166 pLInfo->fAngleXMin = fAngleXMin;
167 pLInfo->fAngleXMax = fAngleXMax;
168 pLInfo->fAngleYMin = fAngleYMin;
169 pLInfo->fAngleYMax = fAngleYMax;
170 pLInfo->fAngleZMin = fAngleZMin;
171 pLInfo->fAngleZMax = fAngleZMax;
172 BuildS(pLInfo);
173
174 pLInfo->eStart = astart;
175 pLInfo->eVect = avect;
176 pLInfo->abFollow = true;
177 pLInfo->anb = anb - (int)(10 * m);
178 pLInfo->anbrec = anbrec + (int)(2 * m);
179 pLInfo->aParent = moi;
180 pLInfo->fAngleXMin = fAngleXMin;
181 pLInfo->fAngleXMax = fAngleXMax;
182 pLInfo->fAngleYMin = fAngleYMin;
183 pLInfo->fAngleYMax = fAngleYMax;
184 pLInfo->fAngleZMin = fAngleZMin;
185 pLInfo->fAngleZMax = fAngleZMax;
186 BuildS(pLInfo);
187 }
188 else
189 {
190 pLInfo->abFollow = false;
191 pLInfo->eStart = astart;
192 pLInfo->eVect = avect;
193 pLInfo->anb = anb - (int)(10 * (1 - m));
194 pLInfo->anbrec = anbrec + (int)(2 * m);
195 pLInfo->aParent = moi;
196 pLInfo->fAngleXMin = fAngleXMin;
197 pLInfo->fAngleXMax = fAngleXMax;
198 pLInfo->fAngleYMin = fAngleYMin;
199 pLInfo->fAngleYMax = fAngleYMax;
200 pLInfo->fAngleZMin = fAngleZMin;
201 pLInfo->fAngleZMax = fAngleZMax;
202 BuildS(pLInfo);
203
204 pLInfo->abFollow = false;
205 pLInfo->eStart = astart;
206 pLInfo->eVect = avect;
207 pLInfo->anb = anb - (int)(10 * m);
208 pLInfo->anbrec = anbrec + (int)(2 * m);
209 pLInfo->aParent = moi;
210 pLInfo->fAngleXMin = fAngleXMin;
211 pLInfo->fAngleXMax = fAngleXMax;
212 pLInfo->fAngleYMin = fAngleYMin;
213 pLInfo->fAngleYMax = fAngleYMax;
214 pLInfo->fAngleZMin = fAngleZMin;
215 pLInfo->fAngleZMax = fAngleZMax;
216 BuildS(pLInfo);
217 }
218 }
219
220 else
221 {
222 if (rnd() <= 0.10)
223 {
224 pLInfo->abFollow = true;
225 }
226
227 pLInfo->eStart = astart;
228 pLInfo->eVect = avect;
229 pLInfo->anb = anb - 1;
230 pLInfo->anbrec = anbrec;
231 pLInfo->aParent = moi;
232 pLInfo->fAngleXMin = fAngleXMin;
233 pLInfo->fAngleXMax = fAngleXMax;
234 pLInfo->fAngleYMin = fAngleYMin;
235 pLInfo->fAngleYMax = fAngleYMax;
236 pLInfo->fAngleZMin = fAngleZMin;
237 pLInfo->fAngleZMax = fAngleZMax;
238 BuildS(pLInfo);
239 }
240 }
241 }
242
SetPosSrc(Vec3f aeSrc)243 void CLightning::SetPosSrc(Vec3f aeSrc) {
244 eSrc = aeSrc;
245 }
246
SetPosDest(Vec3f aeDest)247 void CLightning::SetPosDest(Vec3f aeDest) {
248 eDest = aeDest;
249 }
250
SetColor1(float afR,float afG,float afB)251 void CLightning::SetColor1(float afR, float afG, float afB) {
252 fColor1[0] = afR;
253 fColor1[1] = afG;
254 fColor1[2] = afB;
255 }
256
SetColor2(float afR,float afG,float afB)257 void CLightning::SetColor2(float afR, float afG, float afB) {
258 fColor2[0] = afR;
259 fColor2[1] = afG;
260 fColor2[2] = afB;
261 }
262
263
264 float fTotoro = 0;
265 float fMySize = 2;
266
Create(Vec3f aeFrom,Vec3f aeTo,float beta)267 void CLightning::Create(Vec3f aeFrom, Vec3f aeTo, float beta) {
268
269 (void)beta; // TODO removing this parameter makes the signature clash with method from superclass
270
271 SetDuration(ulDuration);
272 SetPosSrc(aeFrom);
273 SetPosDest(aeTo);
274
275 nbtotal = 0;
276
277 if (nbtotal == 0)
278 {
279 fbeta = 0.f;
280 falpha = 1.f;
281
282 LIGHTNING LInfo;
283 memset(&LInfo, 0, sizeof(LIGHTNING));
284
285 LInfo.eStart = eSrc;
286 LInfo.eVect = eDest - eSrc;
287 LInfo.anb = lNbSegments;
288 LInfo.anbrec = 0;
289 LInfo.abFollow = true;
290 LInfo.aParent = 0;
291 LInfo.fAngleXMin = fAngleXMin;
292 LInfo.fAngleXMax = fAngleXMax;
293 LInfo.fAngleYMin = fAngleYMin;
294 LInfo.fAngleYMax = fAngleYMax;
295 LInfo.fAngleZMin = fAngleZMin;
296 LInfo.fAngleZMax = fAngleZMax;
297
298 cnodetab[0].pos = eSrc;
299 cnodetab[0].size = 15;
300 cnodetab[0].parent = 0;
301
302 BuildS(&LInfo);
303 }
304
305
306 float fRandom = 500 + rnd() * 1000;
307
308 iTTL = checked_range_cast<int>(fRandom);
309
310 }
311
312 //------------------------------------------------------------------------------
ReCreate()313 void CLightning::ReCreate()
314 {
315 nbtotal = 0;
316
317 if (nbtotal == 0)
318 {
319
320 falpha = 1.f;
321
322 LIGHTNING LInfo;
323 memset(&LInfo, 0, sizeof(LIGHTNING));
324
325 LInfo.eStart = eSrc;
326 LInfo.eVect = eDest - eSrc;
327 LInfo.anb = lNbSegments;
328 LInfo.anbrec = 0;
329 LInfo.abFollow = true;
330 LInfo.aParent = 0;
331 LInfo.fAngleXMin = fAngleXMin;
332 LInfo.fAngleXMax = fAngleXMax;
333 LInfo.fAngleYMin = fAngleYMin;
334 LInfo.fAngleYMax = fAngleYMax;
335 LInfo.fAngleZMin = fAngleZMin;
336 LInfo.fAngleZMax = fAngleZMax;
337
338 cnodetab[0].pos = eSrc;
339 cnodetab[0].size = 8;
340 cnodetab[0].parent = 0;
341
342 BuildS(&LInfo);
343 }
344
345
346 float fRandom = 500 + rnd() * 1000;
347
348 iTTL = checked_range_cast<int>(fRandom);
349
350
351 }
352
353 //------------------------------------------------------------------------------
Update(unsigned long _ulTime)354 void CLightning::Update(unsigned long _ulTime)
355 {
356 ulCurrentTime += _ulTime;
357 iTTL -= _ulTime;
358 fTotoro += 8;
359
360 if (fMySize > 0.3f)
361 fMySize -= 0.1f;
362 }
GetChestPos(long num,Vec3f * p)363 void GetChestPos(long num, Vec3f * p)
364 {
365 if (num == 0)
366 {
367 p->x = player.pos.x;
368 p->y = player.pos.y + 70.f;
369 p->z = player.pos.z;
370 return;
371 }
372
373 if (ValidIONum(num))
374 {
375 long idx = GetGroupOriginByName(entities[num]->obj, "chest");
376
377 if(idx >= 0) {
378 *p = entities[num]->obj->vertexlist3[idx].v;
379 }
380 else
381 {
382 p->x = entities[num]->pos.x;
383 p->y = entities[num]->pos.y - 120.f;
384 p->z = entities[num]->pos.z;
385 }
386 }
387 }
388 //------------------------------------------------------------------------------
Render()389 float CLightning::Render()
390 {
391 TexturedVertex v[4];
392 TexturedVertex v2[4];
393
394 if (ulCurrentTime >= ulDuration) return 0.f;
395
396 falpha = 1.f - (((float)(ulCurrentTime)) * fOneOnDuration);
397
398 if (falpha > 1.f) falpha = 1.f;
399
400 if (iTTL <= 0)
401 {
402 fTotoro = 0;
403 fMySize = 2;
404 ReCreate();
405 }
406
407 falpha = 1;
408
409 long i;
410
411 Vec3f ePos;
412
413 float fBeta = 0.f;
414 falpha = 0.f;
415
416 // Create hand position if a hand is defined
417 // spells[spellinstance].hand_group=entities[spells[spellinstance].caster]->obj->fastaccess.primary_attach;//GetActionPointIdx(entities[spells[spellinstance].caster]->obj,"primary_attach");
418 // Player source
419 if(spells[spellinstance].type == SPELL_MASS_LIGHTNING_STRIKE) {
420 arx_assert(lSrc == -1); //ARX: jycorbel (2010-07-19) - We really need ePos when lSrc!=-1 ; in that case lSrc should be equal to -1 !
421 ePos = Vec3f::ZERO;
422 } else {
423
424 Entity * caster = entities[spells[spellinstance].caster];
425 long idx = GetGroupOriginByName(caster->obj, "chest");
426 if(idx >= 0) {
427 spells[spellinstance].caster_pos = caster->obj->vertexlist3[idx].v;
428 } else {
429 spells[spellinstance].caster_pos = caster->pos;
430 }
431
432 if(spells[spellinstance].caster == 0) {
433 falpha = -player.angle.a;
434 fBeta = player.angle.b;
435 } else {
436 // IO source
437 fBeta = caster->angle.b;
438 if(ValidIONum(caster->targetinfo)
439 && caster->targetinfo != spells[spellinstance].caster) {
440 Vec3f * p1 = &spells[spellinstance].caster_pos;
441 Vec3f p2;
442 GetChestPos(caster->targetinfo, &p2);
443 falpha = MAKEANGLE(degrees(getAngle(p1->y, p1->z, p2.y, p2.z + dist(Vec2f(p2.x, p2.z), Vec2f(p1->x, p1->z))))); //alpha entre orgn et dest;
444 }
445 else if (ValidIONum(spells[spellinstance].target))
446 {
447 Vec3f * p1 = &spells[spellinstance].caster_pos;
448 Vec3f p2;
449 GetChestPos(spells[spellinstance].target, &p2); //
450 falpha = MAKEANGLE(degrees(getAngle(p1->y, p1->z, p2.y, p2.z + dist(Vec2f(p2.x, p2.z), Vec2f(p1->x, p1->z))))); //alpha entre orgn et dest;
451 }
452 }
453
454 ePos = spells[spellinstance].caster_pos;
455 }
456
457 //-------------------------------------------------------------------------
458 // rendu
459
460 GRenderer->SetCulling(Renderer::CullNone);
461 GRenderer->SetRenderState(Renderer::DepthWrite, false);
462
463 float f = 1.5f * fMySize;
464 cnodetab[0].f = randomVec(-f, f);
465
466 GRenderer->SetBlendFunc(Renderer::BlendOne, Renderer::BlendOne);
467 GRenderer->SetRenderState(Renderer::AlphaBlending, true);
468 GRenderer->ResetTexture(0);
469
470 v2[0].color = v2[1].color = v2[2].color = v2[3].color = Color::white.toBGR();
471
472 float xx;
473 float zz;
474
475 fbeta = fBeta + rnd() * 2 * fMySize;
476
477 for(i = 0; i < nbtotal && i <= fTotoro; i++) {
478 Vec3f astart = cnodetab[cnodetab[i].parent].pos + cnodetab[cnodetab[i].parent].f;
479 float temp = 1.5f * fMySize;
480 Vec3f z_z = cnodetab[cnodetab[i].parent].f + randomVec(-temp, temp);
481 zz = cnodetab[i].size + cnodetab[i].size * 0.3f * rnd();
482 xx = (float)(cnodetab[i].size * cos(radians(-fbeta)));
483 cnodetab[i].f = z_z;
484
485 Vec3f a = cnodetab[i].pos + z_z;
486 if(lSrc != -1) {
487 Vec3f vv2;
488 Vec3f vv1 = astart;
489 VRotateX(&vv1, (falpha));
490 Vector_RotateY(&vv2, &vv1, 180 - MAKEANGLE(fBeta));
491 astart = vv2;
492 vv1 = a;
493 VRotateX(&vv1, (falpha));
494 Vector_RotateY(&vv2, &vv1, 180 - MAKEANGLE(fBeta));
495 a = vv2;
496 astart += ePos;
497 a += ePos;
498 }
499
500 if(i % 4 == 0) {
501 EERIE_SPHERE sphere;
502 sphere.origin = a;
503 sphere.radius = std::min(cnodetab[i].size, 50.f);
504
505 if (CheckAnythingInSphere(&sphere, spells[spellinstance].caster, CAS_NO_SAME_GROUP))
506 {
507 long si = ARX_DAMAGES_GetFree();
508
509 if (si != -1)
510 {
511 damages[si].pos = sphere.origin;
512 damages[si].radius = sphere.radius;
513 damages[si].damages = fDamage * spells[spellinstance].caster_level * ( 1.0f / 3 );
514 damages[si].area = DAMAGE_FULL;
515 damages[si].duration = 1;
516 damages[si].source = spells[spellinstance].caster;
517 damages[si].flags = DAMAGE_FLAG_DONT_HURT_SOURCE | DAMAGE_FLAG_ADD_VISUAL_FX;
518 damages[si].type = DAMAGE_TYPE_FAKEFIRE | DAMAGE_TYPE_MAGICAL | DAMAGE_TYPE_LIGHTNING;
519 damages[si].exist = true;
520 }
521 }
522 }
523
524 // version 4 faces
525 v2[0].color = v2[3].color = 0xFFFFFFFF;
526 v2[1].color = v2[2].color = 0xFF00005A;
527 v2[0].uv = Vec2f(0.5f, 0.f);
528 v2[1].uv = Vec2f::ZERO;
529 v2[2].uv = Vec2f::Y_AXIS;
530 v2[3].uv = Vec2f(0.5f, 1.f);
531 v[0].p = astart;
532 v[1].p = astart + Vec3f(0.f, zz, 0.f);
533 v[2].p = a + Vec3f(0.f, zz, 0.f);
534 v[3].p = a;
535 EE_RT2(&v[0], &v2[0]);
536 EE_RT2(&v[1], &v2[1]);
537 EE_RT2(&v[2], &v2[2]);
538 EE_RT2(&v[3], &v2[3]);
539 ARX_DrawPrimitive(&v2[0], &v2[1], &v2[2]);
540 ARX_DrawPrimitive(&v2[0], &v2[2], &v2[3]);
541
542 v2[0].uv = Vec2f(0.5f, 0.f);
543 v2[1].uv = Vec2f::X_AXIS;
544 v2[2].uv = Vec2f::ONE;
545 v2[3].uv = Vec2f(0.5f, 1.f);
546 v[1].p = astart - Vec3f(0.f, zz, 0.f);
547 v[2].p = a - Vec3f(0.f, zz, 0.f);
548 EE_RT2(&v[1], &v2[1]);
549 EE_RT2(&v[2], &v2[2]);
550 ARX_DrawPrimitive(&v2[0], &v2[1], &v2[2]);
551 ARX_DrawPrimitive(&v2[0], &v2[2], &v2[3]);
552
553 zz *= (float) sin(radians(fbeta));
554
555 v2[1].uv = Vec2f::X_AXIS;
556 v2[2].uv = Vec2f::ONE;
557 v[1].p = astart + Vec3f(xx, 0.f, zz);
558 v[2].p = a + Vec3f(xx, 0.f, zz);
559 EE_RT2(&v[1], &v2[1]);
560 EE_RT2(&v[2], &v2[2]);
561 ARX_DrawPrimitive(&v2[0], &v2[1], &v2[2]);
562 ARX_DrawPrimitive(&v2[0], &v2[2], &v2[3]);
563
564 v2[1].uv = Vec2f::ZERO;
565 v2[2].uv = Vec2f::Y_AXIS;
566 v[1].p = astart - Vec3f(xx, 0.f, zz);
567 v[2].p = a - Vec3f(xx, 0.f, zz);
568 EE_RT2(&v[1], &v2[1]);
569 EE_RT2(&v[2], &v2[2]);
570 ARX_DrawPrimitive(&v2[0], &v2[1], &v2[2]);
571 ARX_DrawPrimitive(&v2[0], &v2[2], &v2[3]);
572 }
573
574 GRenderer->SetRenderState(Renderer::DepthWrite, true);
575 GRenderer->SetRenderState(Renderer::AlphaBlending, false);
576
577 return falpha;
578 }
579
580 //-----------------------------------------------------------------------------
~CConfuse()581 CConfuse::~CConfuse()
582 {
583 spapi_count--;
584
585 if (spapi && (spapi_count <= 0))
586 {
587 spapi_count = 0;
588 delete spapi;
589 spapi = NULL;
590 }
591 }
592
CConfuse()593 CConfuse::CConfuse() {
594
595 eSrc = Vec3f::ZERO;
596 eTarget = Vec3f::ZERO;
597
598 SetDuration(5000);
599 ulCurrentTime = ulDuration + 1;
600
601 tex_p1 = TextureContainer::Load("graph/obj3d/textures/(fx)_tsu_blueting");
602 tex_trail = TextureContainer::Load("graph/obj3d/textures/(fx)_bandelette_blue");
603
604 if(!spapi) {
605 spapi = LoadTheObj("graph/obj3d/interactive/fix_inter/fx_papivolle/fx_papivolle.teo");
606 }
607 spapi_count++;
608
609 const char tex[] = "graph/obj3d/interactive/fix_inter/fx_papivolle/fx_papivolle.tea";
610 ANIM_HANDLE * anim_papii = EERIE_ANIMMANAGER_Load(tex);
611
612 fColor[0] = 0.3f;
613 fColor[1] = 0.3f;
614 fColor[2] = 0.8f;
615
616 ANIM_Set(&au, anim_papii);
617 au.next_anim = NULL;
618 au.cur_anim = anim_papii;
619 au.ctime = 0;
620 au.flags = EA_LOOP;
621 au.nextflags = 0;
622 au.lastframe = 0;
623 au.pour = 0;
624 au.fr = 0;
625 au.altidx_cur = 0;
626 au.altidx_next = 0;
627 }
628
Create(Vec3f aeSrc,float afBeta)629 void CConfuse::Create(Vec3f aeSrc, float afBeta) {
630
631 SetDuration(ulDuration);
632 eSrc = aeSrc;
633 SetAngle(afBeta);
634 fSize = 1;
635 bDone = true;
636 eTarget = entities[spells[spellinstance].target]->pos;
637 end = 20 - 1;
638 }
639
Update(unsigned long _ulTime)640 void CConfuse::Update(unsigned long _ulTime) {
641 ulCurrentTime += _ulTime;
642 iElapsedTime = _ulTime;
643 }
644
Render()645 float CConfuse::Render() {
646
647 int i = 0;
648
649 eTarget = entities[spells[spellinstance].target]->pos;
650
651 if(ulCurrentTime >= ulDuration) {
652 return 0.f;
653 }
654
655 GRenderer->SetRenderState(Renderer::DepthWrite, false);
656 GRenderer->SetBlendFunc(Renderer::BlendOne, Renderer::BlendOne);
657 GRenderer->SetRenderState(Renderer::AlphaBlending, true);
658 GRenderer->SetTexture(0, tex_trail);
659
660 eCurPos = entities[spells[spellinstance].target]->pos;
661 if(spells[spellinstance].target != 0) {
662 eCurPos.y += entities[spells[spellinstance].target]->physics.cyl.height - 30.f;
663 }
664
665 long idx = entities[spells[spellinstance].target]->obj->fastaccess.head_group_origin;
666 if(idx >= 0) {
667 eCurPos = entities[spells[spellinstance].target]->obj->vertexlist3[idx].v;
668 eCurPos.y -= 50.f;
669 }
670
671 Vec3f stitepos = eCurPos;
672 Anglef stiteangle = Anglef(0.f, -degrees(arxtime.get_updated() * ( 1.0f / 500 )), 0.f);
673 Color3f stitecolor = Color3f::white;
674 Vec3f stitescale = Vec3f::ONE;
675 DrawEERIEObjEx(spapi, &stiteangle, &stitepos, &stitescale, &stitecolor);
676
677 for(i = 0; i < 6; i++) {
678
679 PARTICLE_DEF * pd = createParticle();
680 if(!pd) {
681 break;
682 }
683
684 float ang = radians(rnd() * 360.f);
685 float rad = rnd() * 15.f;
686 pd->ov = stitepos + Vec3f(-EEsin(ang) * rad, 0.f, EEcos(ang) * rad);
687 pd->move = Vec3f(0.f, rnd() * 3.f + 1.f, 0.f);
688 pd->siz = 0.25f;
689 pd->tolive = Random::get(2300, 3300);
690 pd->tc = tex_p1;
691 pd->special = PARTICLE_GOLDRAIN | FADE_IN_AND_OUT | ROTATING | MODULATE_ROTATION
692 | DISSIPATING;
693 pd->fparam = 0.0000001f;
694 float t1 = rnd() * 0.4f + 0.4f;
695 float t2 = rnd() * 0.6f + 0.2f;
696 float t3 = rnd() * 0.4f + 0.4f;
697 while(EEfabs(t1 - t2) > 0.3f && EEfabs(t2 - t3) > 0.3f) {
698 t1 = rnd() * 0.4f + 0.4f;
699 t2 = rnd() * 0.6f + 0.2f;
700 t3 = rnd() * 0.4f + 0.4f;
701 }
702 pd->rgb = Color3f(t1 * 0.8f, t2 * 0.8f, t3 * 0.8f);
703 }
704
705 if (this->lLightId == -1)
706 this->lLightId = GetFreeDynLight();
707
708 if (this->lLightId != -1)
709 {
710 long id = this->lLightId;
711 DynLight[id].exist = 1;
712 DynLight[id].intensity = 1.3f;
713 DynLight[id].fallstart = 180.f;
714 DynLight[id].fallend = 420.f;
715 DynLight[id].rgb.r = 0.3f + rnd() * ( 1.0f / 5 );
716 DynLight[id].rgb.g = 0.3f;
717 DynLight[id].rgb.b = 0.5f + rnd() * ( 1.0f / 5 );
718 DynLight[id].pos = stitepos;
719 DynLight[id].duration = 200;
720 DynLight[id].extras = 0;
721 }
722
723 return 1;
724 }
725 //-----------------------------------------------------------------------------
726 //
727 // FIRE FIELD
728 //
729 //-----------------------------------------------------------------------------
CFireField()730 CFireField::CFireField()
731 {
732 }
733
734 //-----------------------------------------------------------------------------
~CFireField()735 CFireField::~CFireField()
736 {
737 }
738
739 //-----------------------------------------------------------------------------
Create(float largeur,Vec3f * pos,int _ulDuration)740 void CFireField::Create(float largeur, Vec3f * pos, int _ulDuration)
741 {
742 this->key = 0;
743
744 SetDuration(_ulDuration);
745
746 pos->y -= 50;
747
748 this->pos = *pos;
749 this->demilargeur = largeur * .5f;
750
751 ParticleParams cp;
752 cp.iNbMax = 100;
753 cp.fLife = 2000;
754 cp.fLifeRandom = 1000;
755 cp.p3Pos.x = 80;
756 cp.p3Pos.y = 10;
757 cp.p3Pos.z = 80;
758 cp.p3Direction.x = 0;
759 cp.p3Direction.y = 2;
760 cp.p3Direction.z = 0;
761 cp.fAngle = 0;
762 cp.fSpeed = 0;
763 cp.fSpeedRandom = 0;
764 cp.p3Gravity = Vec3f::ZERO;
765 cp.fFlash = 0;
766 cp.fRotation = 0;
767 cp.bRotationRandomDirection = false;
768 cp.bRotationRandomStart = false;
769
770 cp.fStartSize = 10;
771 cp.fStartSizeRandom = 3;
772 cp.fStartColor[0] = 25;
773 cp.fStartColor[1] = 25;
774 cp.fStartColor[2] = 25;
775 cp.fStartColor[3] = 50;
776 cp.fStartColorRandom[0] = 51;
777 cp.fStartColorRandom[1] = 51;
778 cp.fStartColorRandom[2] = 51;
779 cp.fStartColorRandom[3] = 101;
780 cp.bStartLock = false;
781
782 cp.fEndSize = 10;
783 cp.fEndSizeRandom = 3;
784 cp.fEndColor[0] = 25;
785 cp.fEndColor[1] = 25;
786 cp.fEndColor[2] = 25;
787 cp.fEndColor[3] = 50;
788 cp.fEndColorRandom[0] = 0;
789 cp.fEndColorRandom[1] = 0;
790 cp.fEndColorRandom[2] = 0;
791 cp.fEndColorRandom[3] = 100;
792 cp.bEndLock = false;
793 cp.bTexLoop = true;
794
795 cp.iBlendMode = 3;
796
797 pPSStream.SetParams(cp);
798 pPSStream.ulParticleSpawn = 0;
799
800 pPSStream.SetTexture("graph/particles/firebase", 4, 100);
801
802 pPSStream.fParticleFreq = 150.0f;
803 pPSStream.SetPos(*pos);
804 pPSStream.Update(0);
805
806 //-------------------------------------------------------------------------
807
808 cp.iNbMax = 50;
809 cp.fLife = 1000;
810 cp.fLifeRandom = 500;
811 cp.p3Pos.x = 100;
812 cp.p3Pos.y = 10;
813 cp.p3Pos.z = 100;
814 cp.p3Direction.x = 0;
815 cp.p3Direction.y = -2;
816 cp.p3Direction.z = 0;
817 cp.fAngle = radians(10);
818 cp.fSpeed = 0;
819 cp.fSpeedRandom = 0;
820 cp.p3Gravity = Vec3f::ZERO;
821 cp.fFlash = 0;
822 cp.fRotation = 0;
823 cp.bRotationRandomDirection = false;
824 cp.bRotationRandomStart = false;
825
826 cp.fStartSize = 10;
827 cp.fStartSizeRandom = 10;
828 cp.fStartColor[0] = 40;
829 cp.fStartColor[1] = 40;
830 cp.fStartColor[2] = 40;
831 cp.fStartColor[3] = 50;
832 cp.fStartColorRandom[0] = 51;
833 cp.fStartColorRandom[1] = 51;
834 cp.fStartColorRandom[2] = 51;
835 cp.fStartColorRandom[3] = 100;
836 cp.bStartLock = false;
837
838 cp.fEndSize = 10;
839 cp.fEndSizeRandom = 10;
840 cp.fEndColor[0] = 0;
841 cp.fEndColor[1] = 0;
842 cp.fEndColor[2] = 0;
843 cp.fEndColor[3] = 50;
844 cp.fEndColorRandom[0] = 0;
845 cp.fEndColorRandom[1] = 0;
846 cp.fEndColorRandom[2] = 0;
847 cp.fEndColorRandom[3] = 100;
848 cp.bEndLock = false;
849 cp.bTexLoop = false;
850
851 cp.iBlendMode = 0;
852
853 pPSStream1.SetParams(cp);
854 pPSStream1.ulParticleSpawn = 0;
855
856 pPSStream1.SetTexture("graph/particles/fire", 0, 500);
857
858 pPSStream1.fParticleFreq = 150.0f;
859 Vec3f ea;
860 ea.x = pos->x;
861 ea.z = pos->y + 10;
862 ea.y = pos->z;
863 pPSStream1.SetPos(ea);
864 pPSStream1.Update(0);
865 }
866
867 //-----------------------------------------------------------------------------
Update(unsigned long _ulTime)868 void CFireField::Update(unsigned long _ulTime)
869 {
870 ulCurrentTime += _ulTime;
871
872 pPSStream.Update(_ulTime);
873 pPSStream1.Update(_ulTime);
874 }
875
876 /*--------------------------------------------------------------------------*/
Render()877 float CFireField::Render()
878 {
879 if (this->key > 1) return 0;
880
881 GRenderer->SetRenderState(Renderer::AlphaBlending, true);
882 GRenderer->SetRenderState(Renderer::DepthWrite, false);
883 GRenderer->SetBlendFunc(Renderer::BlendOne, Renderer::BlendOne);
884
885 GRenderer->SetCulling(Renderer::CullNone);
886 GRenderer->SetRenderState(Renderer::DepthWrite, false);
887 GRenderer->SetRenderState(Renderer::AlphaBlending, true);
888
889 pPSStream.Render();
890 pPSStream1.Render();
891
892 GRenderer->SetBlendFunc(Renderer::BlendOne, Renderer::BlendZero);
893 GRenderer->SetRenderState(Renderer::AlphaBlending, false);
894 GRenderer->SetRenderState(Renderer::DepthWrite, true);
895
896 return 0;
897 }
898
899 //-----------------------------------------------------------------------------
~CIceField()900 CIceField::~CIceField()
901 {
902 smotte_count--;
903
904 if (smotte && (smotte_count <= 0))
905 {
906 smotte_count = 0;
907 delete smotte;
908 smotte = NULL;
909 }
910
911 stite_count--;
912
913 if (stite && (stite_count <= 0))
914 {
915 stite_count = 0;
916 delete stite;
917 stite = NULL;
918 }
919 }
920
CIceField()921 CIceField::CIceField() {
922
923 eSrc = Vec3f::ZERO;
924 eTarget = Vec3f::ZERO;
925
926 SetDuration(1000);
927 ulCurrentTime = ulDuration + 1;
928
929 iNumber = 50;
930
931 tex_p1 = TextureContainer::Load("graph/obj3d/textures/(fx)_tsu_blueting");
932 tex_p2 = TextureContainer::Load("graph/obj3d/textures/(fx)_tsu_bluepouf");
933
934 if(!stite) {
935 stite = LoadTheObj("graph/obj3d/interactive/fix_inter/stalagmite/motte.teo");
936 }
937 stite_count++;
938
939 if(!smotte) {
940 smotte = LoadTheObj("graph/obj3d/interactive/fix_inter/stalagmite/motte.teo");
941 }
942 smotte_count++;
943 }
944
Create(Vec3f aeSrc,float afBeta)945 void CIceField::Create(Vec3f aeSrc, float afBeta) {
946
947 SetDuration(ulDuration);
948
949 eSrc = aeSrc;
950
951 fBeta = afBeta;
952 fBetaRad = radians(fBeta);
953 fBetaRadCos = (float) cos(fBetaRad);
954 fBetaRadSin = (float) sin(fBetaRad);
955
956 eTarget = eSrc;
957 iNumber = 50;
958 fSize = 1;
959
960 float xmin, ymin, zmin;
961
962 for (int i = 0 ; i < iNumber ; i++)
963 {
964 float t = rnd();
965
966 if (t < 0.5f)
967 tType[i] = 0;
968 else
969 tType[i] = 1;
970
971 tSize[i] = Vec3f::ZERO;
972 tSizeMax[i].x = rnd();
973 tSizeMax[i].y = rnd() + 0.2f;
974 tSizeMax[i].z = rnd();
975
976 if(tType[i] == 0) {
977 xmin = 1.2f;
978 ymin = 1;
979 zmin = 1.2f;
980 } else {
981 xmin = 0.4f;
982 ymin = 0.3f;
983 zmin = 0.4f;
984 }
985
986 if (tSizeMax[i].x < xmin)
987 tSizeMax[i].x = xmin;
988
989 if (tSizeMax[i].y < ymin)
990 tSizeMax[i].y = ymin;
991
992 if (tSizeMax[i].z < zmin)
993 tSizeMax[i].z = zmin;
994
995 if (tType[i] == 0)
996 {
997 tPos[i].x = eSrc.x + frand2() * 80;
998 tPos[i].y = eSrc.y;
999 tPos[i].z = eSrc.z + frand2() * 80;
1000 }
1001 else
1002 {
1003 tPos[i].x = eSrc.x + frand2() * 120;
1004 tPos[i].y = eSrc.y;
1005 tPos[i].z = eSrc.z + frand2() * 120;
1006 }
1007 }
1008
1009 int j = 0;
1010 iMax = iNumber;
1011
1012 j = 50;
1013
1014 iMax = j;
1015
1016 iNumber = j;
1017 }
1018
1019 //---------------------------------------------------------------------
Update(unsigned long _ulTime)1020 void CIceField::Update(unsigned long _ulTime)
1021 {
1022 ulCurrentTime += _ulTime;
1023 }
1024
1025 //---------------------------------------------------------------------
Render()1026 float CIceField::Render()
1027 {
1028 int i = 0;
1029
1030
1031 GRenderer->SetRenderState(Renderer::DepthWrite, true);
1032 GRenderer->SetBlendFunc(Renderer::BlendOne, Renderer::BlendOne);
1033 GRenderer->SetRenderState(Renderer::AlphaBlending, true);
1034
1035 iMax = (int)(iNumber);
1036
1037 if (iMax > iNumber) iMax = iNumber;
1038
1039 for (i = 0; i < iMax; i++)
1040 {
1041 if (tSize[i].x < tSizeMax[i].x)
1042 tSize[i].x += 0.1f;
1043
1044 if (tSize[i].x > tSizeMax[i].x)
1045 tSize[i].x = tSizeMax[i].x;
1046
1047 if (tSize[i].y < tSizeMax[i].y)
1048 tSize[i].y += 0.1f;
1049
1050 if (tSize[i].y > tSizeMax[i].y)
1051 tSize[i].y = tSizeMax[i].y;
1052
1053 if (tSize[i].z < tSizeMax[i].z)
1054 tSize[i].z += 0.1f;
1055
1056 if (tSize[i].z > tSizeMax[i].z)
1057 tSize[i].z = tSizeMax[i].z;
1058
1059 Anglef stiteangle;
1060 Vec3f stitepos;
1061 Vec3f stitescale;
1062 Color3f stitecolor;
1063
1064 stiteangle.b = (float) cos(radians(tPos[i].x)) * 360;
1065 stiteangle.a = 0;
1066 stiteangle.g = 0;
1067 stitepos.x = tPos[i].x;
1068 stitepos.y = eSrc.y;
1069 stitepos.z = tPos[i].z;
1070
1071 float fcol = 1;
1072
1073 if (abs(iMax - i) < 60)
1074 {
1075 fcol = 1;
1076 }
1077 else
1078 {
1079 }
1080
1081 stitecolor.r = tSizeMax[i].y * fcol * 0.7f;
1082 stitecolor.g = tSizeMax[i].y * fcol * 0.7f;
1083 stitecolor.b = tSizeMax[i].y * fcol * 0.9f;
1084
1085 if (stitecolor.r > 1) stitecolor.r = 1;
1086
1087 if (stitecolor.g > 1) stitecolor.g = 1;
1088
1089 if (stitecolor.b > 1) stitecolor.b = 1;
1090
1091 stitescale.z = tSize[i].x;
1092 stitescale.y = tSize[i].y;
1093 stitescale.x = tSize[i].z;
1094
1095 if (tType[i] == 0)
1096 DrawEERIEObjEx(smotte, &stiteangle, &stitepos, &stitescale, &stitecolor);
1097 else
1098 DrawEERIEObjEx(stite, &stiteangle, &stitepos, &stitescale, &stitecolor);
1099 }
1100
1101 for(i = 0; i < iMax * 0.5f; i++) {
1102
1103 float t = rnd();
1104 if(t < 0.01f) {
1105
1106 PARTICLE_DEF * pd = createParticle();
1107 if(pd) {
1108 pd->ov = tPos[i] + randomVec(-5.f, 5.f);
1109 pd->move = randomVec(-2.f, 2.f);
1110 pd->siz = 20.f;
1111 pd->tolive = Random::get(2000, 6000);
1112 pd->tc = tex_p2;
1113 pd->special = FADE_IN_AND_OUT | ROTATING | MODULATE_ROTATION | DISSIPATING;
1114 pd->fparam = 0.0000001f;
1115 pd->rgb = Color3f(0.7f, 0.7f, 1.f);
1116 }
1117
1118 } else if (t > 0.095f) {
1119
1120 PARTICLE_DEF * pd = createParticle();
1121 if(pd) {
1122 pd->ov = tPos[i] + randomVec(-5.f, 5.f) + Vec3f(0.f, 50.f, 0.f);
1123 pd->move = Vec3f(0.f, 2.f - 4.f * rnd(), 0.f);
1124 pd->siz = 0.5f;
1125 pd->tolive = Random::get(2000, 6000);
1126 pd->tc = tex_p1;
1127 pd->special = FADE_IN_AND_OUT | ROTATING | MODULATE_ROTATION | DISSIPATING;
1128 pd->fparam = 0.0000001f;
1129 pd->rgb = Color3f(0.7f, 0.7f, 1.f);
1130 }
1131
1132 }
1133 }
1134
1135 return 1;
1136 }
1137