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