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/Spells05.h"
46 
47 #include <climits>
48 
49 #include "animation/AnimationRender.h"
50 
51 #include "core/Core.h"
52 #include "core/GameTime.h"
53 
54 #include "game/Damage.h"
55 #include "game/EntityManager.h"
56 #include "game/Player.h"
57 #include "game/Spells.h"
58 
59 #include "graphics/Math.h"
60 #include "graphics/data/TextureContainer.h"
61 #include "graphics/effects/SpellEffects.h"
62 #include "graphics/effects/Fog.h"
63 #include "graphics/particle/ParticleEffects.h"
64 #include "graphics/particle/Particle.h"
65 #include "graphics/particle/ParticleManager.h"
66 #include "graphics/particle/ParticleParams.h"
67 #include "graphics/texture/TextureStage.h"
68 
69 #include "scene/Interactive.h"
70 #include "scene/Light.h"
71 #include "scene/Object.h"
72 
73 #include <list>
74 
75 extern ParticleManager * pParticleManager;
76 
77 
78 EERIE_3DOBJ * ssol = NULL;
79 long ssol_count = 0;
80 EERIE_3DOBJ * slight = NULL;
81 long slight_count = 0;
82 EERIE_3DOBJ * srune = NULL;
83 long srune_count = 0;
84 EERIE_3DOBJ * smotte = NULL;
85 long smotte_count = 0;
86 EERIE_3DOBJ * stite = NULL;
87 long stite_count = 0;
88 EERIE_3DOBJ * smissile = NULL;
89 long smissile_count = 0;
90 EERIE_3DOBJ * spapi = NULL;
91 long spapi_count = 0;
92 EERIE_3DOBJ * svoodoo = NULL;
93 long svoodoo_count = 0;
94 //-----------------------------------------------------------------------------
CCurePoison()95 CCurePoison::CCurePoison()
96 {
97 	SetDuration(1000);
98 	ulCurrentTime = ulDuration + 1;
99 
100 	pPS = new ParticleSystem();
101 }
102 
103 //-----------------------------------------------------------------------------
~CCurePoison()104 CCurePoison::~CCurePoison()
105 {
106 
107 }
108 
109 //-----------------------------------------------------------------------------
Create()110 void CCurePoison::Create()
111 {
112 	SetAngle(0);
113 
114 	eSrc.x = entities[spells[spellinstance].target]->pos.x;
115 	eSrc.y = entities[spells[spellinstance].target]->pos.y;
116 
117 	if (spells[spellinstance].target == 0)
118 		eSrc.y += 200;
119 
120 	eSrc.z = entities[spells[spellinstance].target]->pos.z;
121 
122 	pPS->SetPos(eSrc);
123 	ParticleParams cp;
124 	memset(&cp, 0, sizeof(cp));
125 	cp.iNbMax = 350;
126 	cp.fLife = 800;
127 	cp.fLifeRandom = 2000;
128 	cp.p3Pos.x = 100;
129 	cp.p3Pos.y = 0;
130 	cp.p3Pos.z = 100;
131 	cp.p3Direction.x = 0;
132 	cp.p3Direction.y = -10;
133 	cp.p3Direction.z = 0;
134 	cp.fAngle = radians(5);
135 	cp.fSpeed = 120;
136 	cp.fSpeedRandom = 84;
137 	cp.p3Gravity.x = 0;
138 	cp.p3Gravity.y = -10;
139 	cp.p3Gravity.z = 0;
140 	cp.fFlash = 0;
141 	cp.fRotation = 80;
142 
143 	cp.fStartSize = 8;//6;
144 	cp.fStartSizeRandom = 8;
145 	cp.fStartColor[0] = 20;
146 	cp.fStartColor[1] = 205;
147 	cp.fStartColor[2] = 20;
148 	cp.fStartColor[3] = 245;
149 	cp.fStartColorRandom[0] = 50;
150 	cp.fStartColorRandom[1] = 50;
151 	cp.fStartColorRandom[2] = 50;
152 	cp.fStartColorRandom[3] = 10;
153 
154 	cp.fEndSize = 6;
155 	cp.fEndSizeRandom = 4;
156 	cp.fEndColor[0] = 5;
157 	cp.fEndColor[1] = 20;
158 	cp.fEndColor[2] = 5;
159 	cp.fEndColor[3] = 0;
160 	cp.fEndColorRandom[0] = 0;
161 	cp.fEndColorRandom[1] = 40;
162 	cp.fEndColorRandom[2] = 0;
163 	cp.fEndColorRandom[3] = 0;
164 	cp.bTexInfo = false;
165 	pPS->SetParams(cp);
166 	pPS->ulParticleSpawn = PARTICLE_CIRCULAR | PARTICLE_BORDER;
167 	pPS->SetTexture("graph/particles/cure_poison", 0, 100); //5
168 
169 	pPS->lLightId = GetFreeDynLight();
170 
171 	if (pPS->lLightId != -1)
172 	{
173 		long id = pPS->lLightId;
174 		DynLight[id].exist = 1;
175 		DynLight[id].intensity = 1.5f;
176 		DynLight[id].fallstart = 200.f;
177 		DynLight[id].fallend   = 350.f;
178 		DynLight[id].rgb.r = 0.f;
179 		DynLight[id].rgb.g = 1.f;
180 		DynLight[id].rgb.b = 0.0f;
181 		DynLight[id].pos.x = eSrc.x;
182 		DynLight[id].pos.y = eSrc.y - 50.f;
183 		DynLight[id].pos.z = eSrc.z;
184 		DynLight[id].time_creation = (unsigned long)(arxtime);
185 		DynLight[id].duration = 200;
186 		DynLight[id].extras = 0;
187 	}
188 
189 	fSize = 1;
190 }
191 
192 //---------------------------------------------------------------------
Update(unsigned long aulTime)193 void CCurePoison::Update(unsigned long aulTime)
194 {
195 	ulCurrentTime += aulTime;
196 
197 	if (ulCurrentTime >= ulDuration)
198 	{
199 		return;
200 	}
201 
202 	eSrc.x = entities[spells[spellinstance].target]->pos.x;
203 	eSrc.y = entities[spells[spellinstance].target]->pos.y;
204 
205 	if (spells[spellinstance].target == 0)
206 		eSrc.y += 200;
207 
208 	eSrc.z = entities[spells[spellinstance].target]->pos.z;
209 
210 
211 	unsigned long ulCalc = ulDuration - ulCurrentTime ;
212 	arx_assert(ulCalc <= LONG_MAX);
213 	long ff = 	static_cast<long>(ulCalc);
214 
215 
216 
217 	if (ff < 1500)
218 	{
219 		pPS->uMaxParticles = 0;
220 		pPS->ulParticleSpawn = PARTICLE_CIRCULAR;
221 		pPS->p3ParticleGravity = Vec3f::ZERO;
222 
223 		std::list<Particle *>::iterator i;
224 
225 		for (i = pPS->listParticle.begin(); i != pPS->listParticle.end(); ++i)
226 		{
227 			Particle * pP = *i;
228 
229 			if (pP->isAlive())
230 			{
231 				pP->fColorEnd[3] = 0;
232 
233 				if (pP->ulTime + ff < pP->ulTTL)
234 				{
235 					pP->ulTime = pP->ulTTL - ff;
236 				}
237 			}
238 		}
239 	}
240 
241 	pPS->SetPos(eSrc);
242 	pPS->Update(aulTime);
243 
244 	if (pPS->lLightId == -1) pPS->lLightId = GetFreeDynLight();
245 
246 	if (pPS->lLightId != -1)
247 	{
248 		long id = pPS->lLightId;
249 		DynLight[id].exist = 1;
250 		DynLight[id].intensity = 2.3f;
251 		DynLight[id].fallstart = 200.f;
252 		DynLight[id].fallend   = 350.f;
253 		DynLight[id].rgb.r = 0.4f;
254 		DynLight[id].rgb.g = 1.f;
255 		DynLight[id].rgb.b = 0.4f;
256 		DynLight[id].pos.x = eSrc.x;
257 		DynLight[id].pos.y = eSrc.y - 50.f;
258 		DynLight[id].pos.z = eSrc.z;
259 		DynLight[id].duration = 200;
260 		DynLight[id].time_creation = (unsigned long)(arxtime);
261 		DynLight[id].extras = 0;
262 	}
263 
264 }
265 
266 //---------------------------------------------------------------------
Render()267 float CCurePoison::Render()
268 {
269 	if (ulCurrentTime >= ulDuration)
270 	{
271 		return 0.f;
272 	}
273 
274 	pPS->Render();
275 
276 	return 1;
277 }
278 
CRuneOfGuarding()279 CRuneOfGuarding::CRuneOfGuarding() {
280 
281 	eSrc = Vec3f::ZERO;
282 	eTarget = Vec3f::ZERO;
283 
284 	SetDuration(1000);
285 	ulCurrentTime = ulDuration + 1;
286 
287 	tex_p2 = TextureContainer::Load("graph/obj3d/textures/(fx)_tsu_blueting");
288 
289 	if(!ssol) {
290 		ssol = LoadTheObj("graph/obj3d/interactive/fix_inter/fx_rune_guard/fx_rune_guard.teo");
291 	}
292 	ssol_count++;
293 
294 	if(!slight) {
295 		slight = LoadTheObj("graph/obj3d/interactive/fix_inter/fx_rune_guard/fx_rune_guard02.teo");
296 	}
297 	slight_count++;
298 
299 	if(!srune) {
300 		srune = LoadTheObj("graph/obj3d/interactive/fix_inter/fx_rune_guard/fx_rune_guard03.teo");
301 	}
302 	srune_count++;
303 }
304 
~CRuneOfGuarding()305 CRuneOfGuarding::~CRuneOfGuarding()
306 {
307 	ssol_count--;
308 
309 	if (ssol && (ssol_count <= 0))
310 	{
311 		ssol_count = 0;
312 		delete ssol;
313 		ssol = NULL;
314 	}
315 
316 	slight_count--;
317 
318 	if (slight && (slight_count <= 0))
319 	{
320 		slight_count = 0;
321 		delete slight;
322 		slight = NULL;
323 	}
324 
325 	srune_count--;
326 
327 	if (srune && (srune_count <= 0))
328 	{
329 		srune_count = 0;
330 		delete srune;
331 		srune = NULL;
332 	}
333 }
334 
Create(Vec3f _eSrc,float _fBeta)335 void CRuneOfGuarding::Create(Vec3f _eSrc, float _fBeta) {
336 
337 	SetDuration(ulDuration);
338 	SetAngle(_fBeta);
339 	eSrc = _eSrc;
340 	eTarget = eSrc;
341 	fSize = 1;
342 	bDone = true;
343 
344 	lLightId = GetFreeDynLight();
345 	if(lLightId != -1) {
346 		long id = lLightId;
347 		DynLight[id].exist = 1;
348 		DynLight[id].intensity = 0.7f + 2.3f;
349 		DynLight[id].fallend = 500.f;
350 		DynLight[id].fallstart = 400.f;
351 		DynLight[id].rgb.r = 1.0f;
352 		DynLight[id].rgb.g = 0.2f;
353 		DynLight[id].rgb.b = 0.2f;
354 		DynLight[id].pos = eSrc - Vec3f(0.f, 50.f, 0.f);
355 		DynLight[id].time_creation = (unsigned long)(arxtime);
356 		DynLight[id].duration = 200;
357 	}
358 }
359 
Update(unsigned long _ulTime)360 void CRuneOfGuarding::Update(unsigned long _ulTime) {
361 
362 	ulCurrentTime += _ulTime;
363 
364 	float fa = 1.0f - rnd() * 0.15f;
365 
366 	if (lLightId != -1)
367 	{
368 		long id = lLightId;
369 		DynLight[id].exist = 1;
370 		DynLight[id].intensity = 0.7f + 2.3f * fa;
371 		DynLight[id].fallend = 350.f;
372 		DynLight[id].fallstart = 150.f;
373 		DynLight[id].rgb.r = 1.0f;
374 		DynLight[id].rgb.g = 0.2f;
375 		DynLight[id].rgb.b = 0.2f;
376 		DynLight[id].time_creation = (unsigned long)(arxtime);
377 		DynLight[id].duration = 200;
378 	}
379 }
380 
381 //---------------------------------------------------------------------
Render()382 float CRuneOfGuarding::Render()
383 {
384 
385 
386 	float x = eSrc.x;
387 	float y = eSrc.y - 20;
388 	float z = eSrc.z;
389 
390 	GRenderer->SetRenderState(Renderer::DepthWrite, false);
391 	GRenderer->SetBlendFunc(Renderer::BlendOne, Renderer::BlendOne);
392 	GRenderer->SetRenderState(Renderer::AlphaBlending, true);
393 
394 	Anglef stiteangle;
395 	Color3f stitecolor;
396 
397 	float stiteangleb = (float) ulCurrentTime * fOneOnDuration * 120;
398 	stiteangle.a = 0;
399 	stiteangle.g = 0;
400 	Vec3f stitepos = Vec3f(x, y, z);
401 
402 	float gtc = arxtime.get_updated();
403 	float v = EEsin(gtc * ( 1.0f / 1000 )) * ( 1.0f / 10 );
404 	stiteangle.b = MAKEANGLE(gtc * ( 1.0f / 1000 ));
405 	stitecolor.r = 0.4f - v;
406 	stitecolor.g = 0.4f - v;
407 	stitecolor.b = 0.6f - v;
408 	Vec3f stitescale = Vec3f(1.f, -0.1f, 1.f);
409 
410 	if(slight) {
411 		DrawEERIEObjEx(slight, &stiteangle, &stitepos, &stitescale, &stitecolor);
412 	}
413 
414 	stiteangle.b = stiteangleb;
415 	stitecolor.r = 0.6f;
416 	stitecolor.g = 0.f;
417 	stitecolor.b = 0.f;
418 	stitescale = Vec3f::repeat(2.f);
419 
420 	if(ssol) {
421 		DrawEERIEObjEx(ssol, &stiteangle, &stitepos, &stitescale, &stitecolor);
422 	}
423 
424 	stitecolor.r = 0.6f;
425 	stitecolor.g = 0.3f;
426 	stitecolor.b = 0.45f;
427 	stitescale = Vec3f::repeat(1.8f);
428 
429 	if(srune) {
430 		DrawEERIEObjEx(srune, &stiteangle, &stitepos, &stitescale, &stitecolor);
431 	}
432 
433 	for(int n = 0; n < 4; n++) {
434 
435 		PARTICLE_DEF * pd = createParticle();
436 		if(!pd) {
437 			break;
438 		}
439 
440 		pd->ov = Vec3f(x + frand2() * 40.f, y, z + frand2() * 40.f);
441 		pd->move = Vec3f(0.8f * frand2(), -4.f * rnd(), 0.8f * frand2());
442 		pd->scale = Vec3f::repeat(-0.1f);
443 		pd->tolive = Random::get(2600, 3200);
444 		pd->tc = tex_p2;
445 		pd->siz = 0.3f;
446 		pd->rgb = Color3f(.4f, .4f, .6f);
447 	}
448 
449 	return 1.0f - rnd() * 0.3f;
450 }
451 
LaunchPoisonExplosion(Vec3f * aePos)452 void LaunchPoisonExplosion(Vec3f * aePos) {
453 
454 	// système de partoches pour l'explosion
455 	ParticleSystem * pPS = new ParticleSystem();
456 	ParticleParams cp;
457 	cp.iNbMax = 80;
458 	cp.fLife = 1500;
459 	cp.fLifeRandom = 500;
460 	cp.p3Pos = Vec3f::repeat(5);
461 	cp.p3Direction.x = 0;
462 	cp.p3Direction.y = 4;
463 	cp.p3Direction.z = 0;
464 	cp.fAngle = radians(360);
465 	cp.fSpeed = 200;
466 	cp.fSpeedRandom = 0;
467 	cp.p3Gravity.x = 0;
468 	cp.p3Gravity.y = 17;
469 	cp.p3Gravity.z = 0;
470 	cp.fFlash = 0;
471 	cp.fRotation = 80;
472 	cp.bRotationRandomDirection = true;
473 	cp.bRotationRandomStart = true;
474 
475 	cp.fStartSize = 5;
476 	cp.fStartSizeRandom = 3;
477 	cp.fStartColor[0] = 0;
478 	cp.fStartColor[1] = 76;
479 	cp.fStartColor[2] = 0;
480 	cp.fStartColor[3] = 0;
481 	cp.fStartColorRandom[0] = 0;
482 	cp.fStartColorRandom[1] = 0;
483 	cp.fStartColorRandom[2] = 0;
484 	cp.fStartColorRandom[3] = 150;
485 	cp.bStartLock = false;
486 
487 	cp.fEndSize = 30;
488 	cp.fEndSizeRandom = 5;
489 	cp.fEndColor[0] = 0;
490 	cp.fEndColor[1] = 0;
491 	cp.fEndColor[2] = 0;
492 	cp.fEndColor[3] = 0;
493 	cp.fEndColorRandom[0] = 0;
494 	cp.fEndColorRandom[1] = 25;
495 	cp.fEndColorRandom[2] = 0;
496 	cp.fEndColorRandom[3] = 20;
497 	cp.bEndLock = false;
498 
499 	cp.iBlendMode = 3;
500 	cp.iFreq = -1;
501 	cp.bTexInfo = false;
502 	pPS->SetParams(cp);
503 	pPS->ulParticleSpawn = 0;
504 	pPS->SetTexture("graph/particles/big_greypouf", 0, 200);
505 
506 	pPS->SetPos(*aePos);
507 	pPS->Update(0);
508 	pPS->iParticleNbMax = 0;
509 
510 	std::list<Particle *>::iterator i;
511 
512 	for (i = pPS->listParticle.begin(); i != pPS->listParticle.end(); ++i)
513 	{
514 		Particle * pP = *i;
515 
516 		if (pP->isAlive())
517 		{
518 			if (pP->p3Velocity.y >= 0.5f * 200)
519 				pP->p3Velocity.y = 0.5f * 200;
520 
521 			if (pP->p3Velocity.y <= -0.5f * 200)
522 				pP->p3Velocity.y = -0.5f * 200;
523 		}
524 	}
525 
526 	if (pParticleManager)
527 	{
528 		pParticleManager->AddSystem(pPS);
529 	}
530 }
531 
532 
CPoisonProjectile()533 CPoisonProjectile::CPoisonProjectile() : eSrc(Vec3f::ZERO) {
534 	SetDuration(2000);
535 	ulCurrentTime = ulDuration + 1;
536 }
537 
538 //-----------------------------------------------------------------------------
Create(Vec3f _eSrc,float _fBeta)539 void CPoisonProjectile::Create(Vec3f _eSrc, float _fBeta)
540 {
541 	int i;
542 
543 	SetDuration(ulDuration);
544 
545 	SetAngle(_fBeta);
546 
547 	eSrc = _eSrc;
548 
549 	bOk = false;
550 
551 	eMove = Vec3f(-fBetaRadSin * 2, 0.f, fBetaRadCos * 2);
552 
553 	Vec3f s, e, h;
554 	s = eSrc;
555 	e = eSrc;
556 
557 	i = 0;
558 
559 	while (Visible(&s, &e, NULL, &h) && i < 20)
560 	{
561 		e.x -= fBetaRadSin * 50;
562 		e.z += fBetaRadCos * 50;
563 
564 		i++;
565 	}
566 
567 	e.y += 0.f;
568 
569 	pathways[0].p = eSrc;
570 	pathways[9].p = e;
571 	Split(pathways, 0, 9, 10 * fBetaRadCos, 10, 10, 10, 10 * fBetaRadSin, 10);
572 
573 	if (0)
574 		for (i = 0; i < 10; i++)
575 		{
576 			if (pathways[i].p.y >= eSrc.y + 150)
577 			{
578 				pathways[i].p.y = eSrc.y + 150;
579 			}
580 
581 			if (pathways[i].p.y <= eSrc.y + 50)
582 			{
583 				pathways[i].p.y = eSrc.y + 50;
584 			}
585 		}
586 
587 	fTrail = -1;
588 
589 	//-------------------------------------------------------------------------
590 	// système de partoches
591 	ParticleParams cp;
592 	cp.iNbMax = 5;
593 	cp.fLife = 2000;
594 	cp.fLifeRandom = 1000;
595 	cp.p3Pos = Vec3f::ZERO;
596 	cp.p3Direction = -eMove;
597 	cp.fAngle = 0;
598 	cp.fSpeed = 10;
599 	cp.fSpeedRandom = 10;
600 	cp.p3Gravity = Vec3f::ZERO;
601 	cp.fFlash = 21;
602 	cp.fRotation = 80;
603 	cp.bRotationRandomDirection = true;
604 	cp.bRotationRandomStart = true;
605 
606 	cp.fStartSize = 5;
607 	cp.fStartSizeRandom = 3;
608 	cp.fStartColor[0] = 0;
609 	cp.fStartColor[1] = 50;
610 	cp.fStartColor[2] = 0;
611 	cp.fStartColor[3] = 40;
612 	cp.fStartColorRandom[0] = 0;
613 	cp.fStartColorRandom[1] = 100;
614 	cp.fStartColorRandom[2] = 0;
615 	cp.fStartColorRandom[3] = 50;
616 	cp.bStartLock = false;
617 
618 	cp.fEndSize = 8;
619 	cp.fEndSizeRandom = 13;
620 	cp.fEndColor[0] = 0;
621 	cp.fEndColor[1] = 60;
622 	cp.fEndColor[2] = 0;
623 	cp.fEndColor[3] = 40;
624 	cp.fEndColorRandom[0] = 0;
625 	cp.fEndColorRandom[1] = 100;
626 	cp.fEndColorRandom[2] = 0;
627 	cp.fEndColorRandom[3] = 50;
628 	cp.bEndLock = false;
629 
630 	cp.iBlendMode = 5;
631 
632 	pPS.SetParams(cp);
633 	pPS.ulParticleSpawn = 0;
634 
635 	pPS.SetTexture("graph/particles/big_greypouf", 0, 200);
636 
637 	pPS.fParticleFreq = -1;
638 
639 	pPS.bParticleFollow = true;
640 
641 	pPS.SetPos(eSrc);
642 	pPS.Update(0);
643 }
644 
Update(unsigned long _ulTime)645 void CPoisonProjectile::Update(unsigned long _ulTime)
646 {
647 	if (ulCurrentTime <= 2000)
648 	{
649 		ulCurrentTime += _ulTime;
650 	}
651 
652 	// on passe de 5 à 100 partoches en 1.5secs
653 	if (ulCurrentTime < 750)
654 	{
655 		pPS.iParticleNbMax = 2;
656 		pPS.Update(_ulTime);
657 	}
658 	else
659 	{
660 		if (!bOk)
661 		{
662 			bOk = true;
663 
664 			// go
665 			ParticleParams cp;
666 			cp.iNbMax = 100;
667 			cp.fLife = 500;
668 			cp.fLifeRandom = 300;
669 			cp.p3Pos.x = fBetaRadSin * 20;
670 			cp.p3Pos.y = 0.f;
671 			cp.p3Pos.z = fBetaRadCos * 20;
672 
673 			cp.p3Direction = -eMove;
674 
675 			cp.fAngle = radians(4);
676 			cp.fSpeed = 150;
677 			cp.fSpeedRandom = 50;//15;
678 			cp.p3Gravity.x = 0;
679 			cp.p3Gravity.y = 10;
680 			cp.p3Gravity.z = 0;
681 			cp.fFlash = 0;
682 			cp.fRotation = 80;
683 			cp.bRotationRandomDirection = true;
684 			cp.bRotationRandomStart = true;
685 
686 			cp.fStartSize = 2;
687 			cp.fStartSizeRandom = 2;
688 			cp.fStartColor[0] = 0;
689 			cp.fStartColor[1] = 39;
690 			cp.fStartColor[2] = 0;
691 			cp.fStartColor[3] = 100;
692 			cp.fStartColorRandom[0] = 50;
693 			cp.fStartColorRandom[1] = 21;
694 			cp.fStartColorRandom[2] = 0;
695 			cp.fStartColorRandom[3] = 0;
696 			cp.bStartLock = false;
697 
698 			cp.fEndSize = 7;
699 			cp.fEndSizeRandom = 5;
700 			cp.fEndColor[0] = 0;
701 			cp.fEndColor[1] = 25;
702 			cp.fEndColor[2] = 0;
703 			cp.fEndColor[3] = 100;
704 			cp.fEndColorRandom[0] = 50;
705 			cp.fEndColorRandom[1] = 20;
706 			cp.fEndColorRandom[2] = 0;
707 			cp.fEndColorRandom[3] = 0;
708 			cp.bEndLock = false;
709 
710 			cp.iBlendMode = 5;
711 			cp.bTexInfo = false;
712 			pPSStream.SetParams(cp);
713 			pPSStream.ulParticleSpawn = 0;
714 
715 			pPSStream.SetTexture("graph/particles/big_greypouf", 0, 200);
716 
717 			pPSStream.fParticleFreq = 80;
718 			pPSStream.bParticleFollow = true;
719 		}
720 
721 		pPSStream.Update(_ulTime);
722 		pPSStream.SetPos(eCurPos);
723 
724 		pPS.Update(_ulTime);
725 		pPS.SetPos(eCurPos);
726 
727 		fTrail = ((ulCurrentTime - 750) * (1.0f / (ulDuration - 750.0f))) * 9 * (BEZIERPrecision + 2);
728 	}
729 }
730 
Render()731 float CPoisonProjectile::Render() {
732 
733 	if(ulCurrentTime >= ulDuration) {
734 		return 0.f;
735 	}
736 
737 	GRenderer->SetCulling(Renderer::CullNone);
738 	GRenderer->SetRenderState(Renderer::DepthWrite, false);
739 	GRenderer->SetBlendFunc(Renderer::BlendOne, Renderer::BlendOne);
740 	GRenderer->SetRenderState(Renderer::AlphaBlending, true);
741 
742 	int n = BEZIERPrecision;
743 	float delta = 1.0f / n;
744 
745 	Vec3f lastpos = pathways[0].p;
746 
747 	int arx_check_init = -1;
748 
749 	int i = 0;
750 	for(i = 0; i < 9; i++) {
751 
752 		int kpprec = std::max(i - 1, 0);
753 		int kpsuiv = i + 1 ;
754 		int kpsuivsuiv = (i < (9 - 2)) ? kpsuiv + 1 : kpsuiv;
755 
756 		for(int toto = 1; toto < n; toto++) {
757 
758 			if(fTrail < i * n + toto) {
759 				break;
760 			}
761 
762 			float t = toto * delta;
763 
764 			float t2 = t * t ;
765 			float t3 = t2 * t ;
766 			float f0 = 2.f * t3 - 3.f * t2 + 1.f ;
767 			float f1 = -2.f * t3 + 3.f * t2 ;
768 			float f2 = t3 - 2.f * t2 + t ;
769 			float f3 = t3 - t2 ;
770 
771 			float val = pathways[kpsuiv].p.x;
772 			float p0 = 0.5f * (val - pathways[kpprec].p.x);
773 			float p1 = 0.5f * (pathways[kpsuivsuiv].p.x - pathways[i].p.x);
774 			lastpos.x = f0 * pathways[i].p.x + f1 * val + f2 * p0 + f3 * p1;
775 
776 			val = pathways[kpsuiv].p.y;
777 			p0 = 0.5f * (val - pathways[kpprec].p.y);
778 			p1 = 0.5f * (pathways[kpsuivsuiv].p.y - pathways[i].p.y);
779 			lastpos.y = f0 * pathways[i].p.y + f1 * val + f2 * p0 + f3 * p1;
780 
781 			val = pathways[kpsuiv].p.z;
782 			p0 = 0.5f * (val - pathways[kpprec].p.z);
783 			p1 = 0.5f * (pathways[kpsuivsuiv].p.z - pathways[i].p.z);
784 			lastpos.z = f0 * pathways[i].p.z + f1 * val + f2 * p0 + f3 * p1;
785 
786 			++arx_check_init;
787 		}
788 	}
789 
790 	// arx_assert(arx_check_init >= 0); TODO why should this hold?
791 
792 	eCurPos = lastpos;
793 
794 	if(fTrail >= (i * n)) {
795 		LaunchPoisonExplosion(&lastpos);
796 	}
797 
798 	GRenderer->SetCulling(Renderer::CullNone);
799 	GRenderer->SetRenderState(Renderer::DepthWrite, false);
800 	GRenderer->SetRenderState(Renderer::AlphaBlending, true);
801 
802 	return 1;
803 }
804 
805 //-----------------------------------------------------------------------------
806 //-----------------------------------------------------------------------------
CMultiPoisonProjectile(long nbmissiles)807 CMultiPoisonProjectile::CMultiPoisonProjectile(long nbmissiles)
808 {
809 	SetDuration(2000);
810 	uiNumber = min(5L, nbmissiles);
811 	pTab	 = NULL;
812 	pTab	 = new CPoisonProjectile*[uiNumber]();
813 
814 	for(unsigned int i = 0 ; i < uiNumber ; i++) {
815 		pTab[i] = new CPoisonProjectile();
816 		pTab[i]->spellinstance = this->spellinstance;
817 	}
818 }
819 
820 //-----------------------------------------------------------------------------
~CMultiPoisonProjectile()821 CMultiPoisonProjectile::~CMultiPoisonProjectile()
822 {
823 	for (unsigned int i = 0 ; i < uiNumber ; i++)
824 	{
825 		if (pTab[i]->lLightId != -1)
826 		{
827 			DynLight[pTab[i]->lLightId].duration	  = 2000;
828 			DynLight[pTab[i]->lLightId].time_creation = (unsigned long)(arxtime);
829 			pTab[i]->lLightId						  = -1;
830 		}
831 
832 		delete pTab[i];
833 	}
834 
835 	delete [] pTab;
836 }
837 
838 //-----------------------------------------------------------------------------
Create(Vec3f _eSrc,float _afBeta=0)839 void CMultiPoisonProjectile::Create(Vec3f _eSrc, float _afBeta = 0) {
840 
841 	(void)_afBeta;
842 
843 	float afBeta = 0.f;
844 
845 	Entity * caster = entities[spells[spellinstance].caster];
846 	spells[spellinstance].hand_group = caster->obj->fastaccess.primary_attach;
847 	if(spells[spellinstance].hand_group != -1) {
848 		long group = spells[spellinstance].hand_group;
849 		spells[spellinstance].hand_pos = caster->obj->vertexlist3[group].v;
850 	}
851 
852 	if (spells[spellinstance].caster == 0) // player
853 	{
854 		afBeta = player.angle.b;
855 
856 		if (spells[spellinstance].hand_group != -1)
857 		{
858 			_eSrc.x = spells[spellinstance].hand_pos.x - EEsin(radians(afBeta)) * 90;
859 			_eSrc.y = spells[spellinstance].hand_pos.y;
860 			_eSrc.z = spells[spellinstance].hand_pos.z + EEcos(radians(afBeta)) * 90;
861 		}
862 		else
863 		{
864 			_eSrc.x = player.pos.x - EEsin(radians(afBeta)) * 90;
865 			_eSrc.y = player.pos.y;
866 			_eSrc.z = player.pos.z + EEcos(radians(afBeta)) * 90;
867 		}
868 	}
869 	else
870 	{
871 		afBeta = entities[spells[spellinstance].caster]->angle.b;
872 
873 		if (spells[spellinstance].hand_group != -1)
874 		{
875 			_eSrc.x = spells[spellinstance].hand_pos.x - EEsin(radians(afBeta)) * 90;
876 			_eSrc.y = spells[spellinstance].hand_pos.y;
877 			_eSrc.z = spells[spellinstance].hand_pos.z + EEcos(radians(afBeta)) * 90;
878 		}
879 		else
880 		{
881 			_eSrc.x = entities[spells[spellinstance].caster]->pos.x - EEsin(radians(afBeta)) * 90;
882 			_eSrc.y = entities[spells[spellinstance].caster]->pos.y;
883 			_eSrc.z = entities[spells[spellinstance].caster]->pos.z + EEcos(radians(afBeta)) * 90;
884 		}
885 	}
886 
887 
888 	long lMax = 0;
889 
890 	for (unsigned int i = 0 ; i < uiNumber ; i++)
891 	{
892 		pTab[i]->Create(_eSrc, afBeta + frand2() * 10.0f);
893 		long lTime = ulDuration + Random::get(0, 5000);
894 		pTab[i]->SetDuration(lTime);
895 		lMax = max(lMax, lTime);
896 
897 		CPoisonProjectile * pPP = (CPoisonProjectile *) pTab[i];
898 
899 		pPP->lLightId = GetFreeDynLight();
900 
901 		if (pPP->lLightId != -1)
902 		{
903 			long id						= pPP->lLightId;
904 			DynLight[id].exist			= 1;
905 			DynLight[id].intensity		= 2.3f;
906 			DynLight[id].fallend		= 250.f;
907 			DynLight[id].fallstart		= 150.f;
908 			DynLight[id].rgb = Color3f::green;
909 			DynLight[id].pos = pPP->eSrc;
910 			DynLight[id].time_creation	= (unsigned long)(arxtime);
911 			DynLight[id].duration		= 200;
912 		}
913 
914 		pTab[i]->spellinstance = this->spellinstance;
915 
916 	}
917 
918 	SetDuration(lMax + 1000);
919 }
920 
921 //-----------------------------------------------------------------------------
Update(unsigned long _ulTime)922 void CMultiPoisonProjectile::Update(unsigned long _ulTime)
923 {
924 	for (unsigned int i = 0 ; i < uiNumber ; i++)
925 	{
926 		pTab[i]->Update(_ulTime);
927 	}
928 }
929 
930 //-----------------------------------------------------------------------------
Render()931 float CMultiPoisonProjectile::Render()
932 {
933 
934 
935 	for (unsigned int i = 0 ; i < uiNumber ; i++)
936 	{
937 		float fa = pTab[i]->Render();
938 
939 		CPoisonProjectile * pPoisonProjectile = (CPoisonProjectile *) pTab[i];
940 
941 		if (pPoisonProjectile->lLightId != -1)
942 		{
943 			long id					= pPoisonProjectile->lLightId;
944 			DynLight[id].exist		= 1;
945 			DynLight[id].intensity	= 2.3f * fa;
946 			DynLight[id].fallend	= 250.f;
947 			DynLight[id].fallstart	= 150.f;
948 			DynLight[id].rgb = Color3f::green;
949 			DynLight[id].pos = pPoisonProjectile->eCurPos;
950 			DynLight[id].time_creation = (unsigned long)(arxtime);
951 			DynLight[id].duration	= 200;
952 		}
953 
954 		long t = ARX_DAMAGES_GetFree();
955 		AddPoisonFog(&pPoisonProjectile->eCurPos, spells[spellinstance].caster_level + 7);
956 
957 		if ((t != -1)
958 		        &&	(spells[pTab[i]->spellinstance].timcreation + 1600 < (unsigned long)(arxtime)))
959 		{
960 			damages[t].pos = pPoisonProjectile->eCurPos;
961 			damages[t].radius = 120.f;
962 			float v = spells[spellinstance].caster_level;
963 			v = 4.f + v * ( 1.0f / 10 ) * 6.f ;
964 			damages[t].damages	= v * ( 1.0f / 1000 ) * framedelay;
965 			damages[t].area		= DAMAGE_FULL;
966 			damages[t].duration	= static_cast<long>(FrameDiff);
967 			damages[t].source	= spells[spellinstance].caster;
968 			damages[t].flags	= 0;
969 			damages[t].type		= DAMAGE_TYPE_MAGICAL | DAMAGE_TYPE_POISON;
970 			damages[t].exist	= true;
971 		}
972 	}
973 
974 	return 1;
975 }
976 
CRepelUndead()977 CRepelUndead::CRepelUndead() {
978 
979 	eSrc = Vec3f::ZERO;
980 	eTarget = Vec3f::ZERO;
981 
982 	ulCurrentTime = ulDuration + 1;
983 
984 	tex_p2 = TextureContainer::Load("graph/obj3d/textures/(fx)_tsu_blueting");
985 
986 	if(!ssol) { // Pentacle
987 		ssol = LoadTheObj("graph/obj3d/interactive/fix_inter/fx_rune_guard/fx_rune_guard.teo");
988 	}
989 	ssol_count++;
990 
991 	if(!slight) { // Twirl
992 		slight = LoadTheObj("graph/obj3d/interactive/fix_inter/fx_rune_guard/fx_rune_guard02.teo");
993 	}
994 	slight_count++; //runes
995 
996 	if(!srune) {
997 		srune = LoadTheObj("graph/obj3d/interactive/fix_inter/fx_rune_guard/fx_rune_guard03.teo");
998 	}
999 	srune_count++;
1000 }
1001 
~CRepelUndead()1002 CRepelUndead::~CRepelUndead() {
1003 
1004 	ssol_count--;
1005 
1006 	if (ssol && (ssol_count <= 0))
1007 	{
1008 		ssol_count = 0;
1009 		delete ssol;
1010 		ssol = NULL;
1011 	}
1012 
1013 	slight_count--;
1014 
1015 	if (slight && (slight_count <= 0))
1016 	{
1017 		slight_count = 0;
1018 		delete slight;
1019 		slight = NULL;
1020 	}
1021 
1022 	srune_count--;
1023 
1024 	if (srune && (srune_count <= 0))
1025 	{
1026 		srune_count = 0;
1027 		delete srune;
1028 		srune = NULL;
1029 	}
1030 }
1031 
Create(Vec3f aeSrc,float afBeta)1032 void CRepelUndead::Create(Vec3f aeSrc, float afBeta) {
1033 
1034 	SetDuration(ulDuration);
1035 	eTarget = eSrc = aeSrc;
1036 	fBeta = afBeta;
1037 	fBetaRad = radians(fBeta);
1038 	fBetaRadCos = (float)cos(fBetaRad);
1039 	fBetaRadSin = (float)sin(fBetaRad);
1040 	fSize = 1;
1041 	bDone = true;
1042 }
1043 
Update(unsigned long _ulTime)1044 void CRepelUndead::Update(unsigned long _ulTime) {
1045 
1046 	ulCurrentTime += _ulTime;
1047 	if(spellinstance < 0) {
1048 		return;
1049 	}
1050 
1051 	eSrc = entities[spells[spellinstance].target]->pos;
1052 
1053 	if(spells[spellinstance].target == 0) {
1054 		fBeta = player.angle.b;
1055 	} else {
1056 		fBeta = entities[spells[spellinstance].target]->angle.b;
1057 	}
1058 }
1059 
Render()1060 float CRepelUndead::Render() {
1061 
1062 	if(ulCurrentTime >= ulDuration) {
1063 		return 0.f;
1064 	}
1065 
1066 	GRenderer->SetRenderState(Renderer::DepthWrite, false);
1067 	GRenderer->SetBlendFunc(Renderer::BlendOne, Renderer::BlendOne);
1068 	GRenderer->SetRenderState(Renderer::AlphaBlending, true);
1069 
1070 	Anglef  eObjAngle;
1071 	Vec3f  eObjPos;
1072 	Vec3f  eObjScale;
1073 	Color3f rgbObjColor;
1074 
1075 	eObjAngle.b = fBeta;
1076 	eObjAngle.a = 0;
1077 	eObjAngle.g = 0;
1078 	eObjPos.x = eSrc.x;
1079 	eObjPos.y = eSrc.y - 5.f;
1080 	eObjPos.z = eSrc.z;
1081 	rgbObjColor.r = 0.6f;
1082 	rgbObjColor.g = 0.6f;
1083 	rgbObjColor.b = 0.8f;
1084 
1085 	float vv = 1.f + (EEsin(arxtime.get_updated() * ( 1.0f / 1000 )));
1086 	vv *= ( 1.0f / 2 );
1087 	vv += 1.1f;
1088 	eObjScale.z = vv;
1089 	eObjScale.y = vv;
1090 	eObjScale.x = vv;
1091 
1092 	if(ssol) {
1093 		DrawEERIEObjEx(ssol, &eObjAngle, &eObjPos, &eObjScale, &rgbObjColor);
1094 	}
1095 
1096 	vv *= 100.f;
1097 
1098 	for(int n = 0; n < 4; n++) {
1099 
1100 		PARTICLE_DEF * pd = createParticle();
1101 		if(!pd) {
1102 			break;
1103 		}
1104 
1105 		float dx = -EEsin(frand2() * 360.f) * vv;
1106 		float dz =  EEcos(frand2() * 360.f) * vv;
1107 		pd->ov = eSrc + Vec3f(dx, 0.f, dz);
1108 		pd->move = Vec3f(0.8f * frand2(), -4.f * rnd(), 0.8f * frand2());
1109 		pd->scale = Vec3f::repeat(-0.1f);
1110 		pd->tolive = Random::get(2600, 3200);
1111 		pd->tc = tex_p2;
1112 		pd->siz = 0.3f;
1113 		pd->rgb = Color3f(.4f, .4f, .6f);
1114 	}
1115 
1116 	if(lLightId == -1) {
1117 		lLightId = GetFreeDynLight();
1118 	}
1119 
1120 	if(lLightId != -1) {
1121 		long id = lLightId;
1122 		DynLight[id].exist = 1;
1123 		DynLight[id].intensity = 2.3f;
1124 		DynLight[id].fallend = 350.f;
1125 		DynLight[id].fallstart = 150.f;
1126 		DynLight[id].rgb = Color3f(0.8f, 0.8f, 1.f);
1127 		DynLight[id].pos = eSrc + Vec3f(0.f, -50.f, 0.f);
1128 		DynLight[id].duration = 200;
1129 		DynLight[id].time_creation = (unsigned long)(arxtime);
1130 	}
1131 
1132 	return 1;
1133 }
1134 
1135 //-----------------------------------------------------------------------------
1136 //	LEVITATION
1137 //-----------------------------------------------------------------------------
1138 EERIE_3DOBJ * stone1 = NULL;
1139 long stone1_count = 0;
1140 EERIE_3DOBJ * stone0 = NULL;
1141 long stone0_count = 0;
1142 
CLevitate()1143 CLevitate::CLevitate()
1144 {
1145 	int nb = 2;
1146 
1147 	while (nb--)
1148 	{
1149 		this->cone[nb].coned3d = NULL;
1150 		this->cone[nb].coneind = NULL;
1151 		this->cone[nb].conevertex = NULL;
1152 	}
1153 
1154 	if(!stone0) {
1155 		stone0 = loadObject("graph/obj3d/interactive/fix_inter/fx_raise_dead/stone01.teo");
1156 	}
1157 
1158 	stone0_count++;
1159 
1160 	if(!stone1) {
1161 		stone1 = loadObject("graph/obj3d/interactive/fix_inter/fx_raise_dead/stone02.teo");
1162 	}
1163 
1164 	stone1_count++;
1165 }
1166 //-----------------------------------------------------------------------------
~CLevitate()1167 CLevitate::~CLevitate()
1168 {
1169 	stone0_count--;
1170 
1171 	if (stone0 && (stone0_count <= 0))
1172 	{
1173 		stone0_count = 0;
1174 		delete stone0;
1175 		stone0 = NULL;
1176 	}
1177 
1178 	stone1_count--;
1179 
1180 	if (stone1 && (stone1_count <= 0))
1181 	{
1182 		stone1_count = 0;
1183 		delete stone1;
1184 		stone1 = NULL;
1185 	}
1186 }
1187 
CreateConeStrip(float rbase,float rhaut,float hauteur,int def,int numcone)1188 void CLevitate::CreateConeStrip(float rbase, float rhaut, float hauteur, int def,
1189                                 int numcone) {
1190 
1191 	T_CONE & c = cone[numcone];
1192 
1193 	free(c.coned3d);
1194 	free(c.conevertex);
1195 	free(c.coneind);
1196 
1197 	c.conenbvertex = def * 2 + 2;
1198 	c.conenbfaces = def * 2 + 2;
1199 	c.coned3d = (TexturedVertex *)malloc(c.conenbvertex * sizeof(TexturedVertex));
1200 	c.conevertex = (Vec3f *)malloc(c.conenbvertex * sizeof(Vec3f));
1201 	c.coneind = (unsigned short *)malloc(c.conenbvertex * sizeof(unsigned short));
1202 
1203 	Vec3f * vertex = c.conevertex;
1204 	unsigned short * pind = c.coneind;
1205 	unsigned short ind = 0;
1206 	int nb;
1207 	float a = 0.f;
1208 	float da = 360.f / (float)def;
1209 	nb = this->cone[numcone].conenbvertex >> 1;
1210 
1211 	while(nb) {
1212 		*pind++ = ind++;
1213 		*pind++ = ind++;
1214 		*vertex++ = Vec3f(rhaut * EEcos(radians(a)), -hauteur, rhaut * EEsin(radians(a)));
1215 		*vertex++ = Vec3f(rbase * EEcos(radians(a)), 0.f, rbase * EEsin(radians(a)));
1216 		a += da;
1217 		nb--;
1218 	}
1219 }
1220 
Create(int def,float rbase,float rhaut,float hauteur,Vec3f * pos,unsigned long _ulDuration)1221 void CLevitate::Create(int def, float rbase, float rhaut, float hauteur, Vec3f * pos, unsigned long _ulDuration)
1222 {
1223 	SetDuration(_ulDuration);
1224 
1225 	if (def < 3) return;
1226 
1227 	this->CreateConeStrip(rbase, rhaut, hauteur, def, 0);
1228 	this->CreateConeStrip(rbase, rhaut * 1.5f, hauteur * 0.5f, def, 1);
1229 
1230 	this->key = 0;
1231 	this->pos = *pos;
1232 	this->rbase = rbase;
1233 	this->rhaut = rhaut;
1234 	this->hauteur = hauteur;
1235 	this->currdurationang = 0;
1236 	this->scale = 0.f;
1237 	this->ang = 0.f;
1238 	this->def = (short)def;
1239 	this->tsouffle = TextureContainer::Load("graph/obj3d/textures/(fx)_sebsouffle");
1240 
1241 	this->timestone = 0;
1242 	this->nbstone = 0;
1243 
1244 
1245 	this->stone[0] = stone0;
1246 	this->stone[1] = stone1;
1247 
1248 	int nb = 256;
1249 
1250 	while (nb--)
1251 	{
1252 		this->tstone[nb].actif = 0;
1253 	}
1254 }
1255 
AddStone(Vec3f * pos)1256 void CLevitate::AddStone(Vec3f * pos) {
1257 
1258 	if(arxtime.is_paused() || nbstone > 255) {
1259 		return;
1260 	}
1261 
1262 	int nb = 256;
1263 	while(nb--) {
1264 		if(!tstone[nb].actif) {
1265 			nbstone++;
1266 			tstone[nb].actif = 1;
1267 			tstone[nb].numstone = rand() & 1;
1268 			tstone[nb].pos = *pos;
1269 			tstone[nb].yvel = rnd() * -5.f;
1270 			tstone[nb].ang = Anglef(rnd() * 360.f, rnd() * 360.f, rnd() * 360.f);
1271 			tstone[nb].angvel = Anglef(5.f * rnd(), 6.f * rnd(), 3.f * rnd());
1272 			tstone[nb].scale = Vec3f::repeat(0.2f + rnd() * 0.3f);
1273 			tstone[nb].time = Random::get(2000, 2500);
1274 			tstone[nb].currtime = 0;
1275 			break;
1276 		}
1277 	}
1278 }
1279 
DrawStone()1280 void CLevitate::DrawStone()
1281 {
1282 	GRenderer->SetBlendFunc(Renderer::BlendInvDstColor, Renderer::BlendOne);
1283 	GRenderer->SetRenderState(Renderer::AlphaBlending, true);
1284 	int	nb = 256;
1285 
1286 	while (nb--)
1287 	{
1288 		if (this->tstone[nb].actif)
1289 		{
1290 			float a = (float)this->tstone[nb].currtime / (float)this->tstone[nb].time;
1291 
1292 			if (a > 1.f)
1293 			{
1294 				a = 1.f;
1295 				this->tstone[nb].actif = 0;
1296 			}
1297 
1298 			int col = Color4f(Color3f::white, 1.f - a).toBGRA();
1299 
1300 			if (this->stone[this->tstone[nb].numstone])
1301 				DrawEERIEObjExEx(this->stone[this->tstone[nb].numstone], &this->tstone[nb].ang, &this->tstone[nb].pos, &this->tstone[nb].scale, col);
1302 
1303 			PARTICLE_DEF * pd = createParticle();
1304 			if(pd) {
1305 				pd->ov = tstone[nb].pos;
1306 				pd->move = Vec3f(0.f, 3.f * rnd(), 0.f);
1307 				pd->siz = 3.f + 3.f * rnd();
1308 				pd->tolive = 1000;
1309 				pd->timcreation = -(long(arxtime) + 1000l); // TODO WTF?
1310 				pd->special = FIRE_TO_SMOKE | FADE_IN_AND_OUT | ROTATING | MODULATE_ROTATION
1311 				              | DISSIPATING;
1312 				pd->fparam = 0.0000001f;
1313 			}
1314 
1315 			//update mvt
1316 			if (!arxtime.is_paused())
1317 			{
1318 				a = (((float)this->currframetime) * 100.f) / (float)this->tstone[nb].time;
1319 				tstone[nb].pos.y += tstone[nb].yvel * a;
1320 				tstone[nb].ang += tstone[nb].angvel * a;
1321 
1322 				this->tstone[nb].yvel *= 1.f - (1.f / 100.f);
1323 
1324 				this->tstone[nb].currtime += this->currframetime;
1325 			}
1326 		}
1327 	}
1328 
1329 	GRenderer->SetRenderState(Renderer::AlphaBlending, false);
1330 }
1331 
1332 /*--------------------------------------------------------------------------*/
Update(unsigned long _ulTime)1333 void CLevitate::Update(unsigned long _ulTime)
1334 {
1335 	float	a;
1336 
1337 	//animation cone
1338 	if (!arxtime.is_paused()) this->currdurationang += _ulTime;
1339 
1340 	this->ang = (float)this->currdurationang / 1000.f;
1341 
1342 	if (this->ang > 1.f)
1343 	{
1344 		this->currdurationang = 0;
1345 		this->ang = 1.f;
1346 	}
1347 
1348 	if (!arxtime.is_paused()) ulCurrentTime += _ulTime;
1349 
1350 	switch (this->key)
1351 	{
1352 		case 0:
1353 			//monté du cone
1354 			a = (float) ulCurrentTime / 1000.f;
1355 
1356 			if (a > 1.f)
1357 			{
1358 				a = 0.f;
1359 				this->key++;
1360 			}
1361 
1362 			this->scale = a;
1363 			break;
1364 		case 1:
1365 			//animation cone
1366 			this->scale = (float)ulCurrentTime / (float)ulDuration;
1367 
1368 			if (ulCurrentTime >= ulDuration)
1369 			{
1370 				this->scale = 1.f;
1371 				this->key++;
1372 			}
1373 
1374 			break;
1375 	}
1376 
1377 	if (!arxtime.is_paused())
1378 	{
1379 		this->currframetime = _ulTime;
1380 		this->timestone -= _ulTime;
1381 	}
1382 
1383 	if (this->timestone <= 0)
1384 	{
1385 		this->timestone = Random::get(50, 150);
1386 		Vec3f	pos;
1387 
1388 		float r = this->rbase * frand2();
1389 		pos.x = this->pos.x + r;
1390 		pos.y = this->pos.y;
1391 		pos.z = this->pos.z + r;
1392 		this->AddStone(&pos);
1393 	}
1394 }
1395 
1396 /*--------------------------------------------------------------------------*/
Render()1397 float CLevitate::Render()
1398 {
1399 	if (this->key > 1) return 0;
1400 
1401 	GRenderer->SetRenderState(Renderer::AlphaBlending, true);
1402 	GRenderer->SetRenderState(Renderer::DepthWrite, false);
1403 
1404 	//calcul du cone
1405 	TexturedVertex d3dvs, *d3dv;
1406 	Vec3f	* vertex;
1407 	int			nb, nbc, col;
1408 	float		ddu = this->ang;
1409 	float		u = ddu, du = .99999999f / (float)this->def;
1410 
1411 	switch (this->key)
1412 	{
1413 		case 0:
1414 			nbc = 2;
1415 
1416 			while (nbc--)
1417 			{
1418 				vertex = this->cone[nbc].conevertex;
1419 				d3dv = this->cone[nbc].coned3d;
1420 				nb = (this->cone[nbc].conenbvertex) >> 1;
1421 
1422 				while (nb)
1423 				{
1424 					d3dvs.p.x = this->pos.x + (vertex + 1)->x + ((vertex->x - (vertex + 1)->x) * this->scale);
1425 					d3dvs.p.y = this->pos.y + (vertex + 1)->y + ((vertex->y - (vertex + 1)->y) * this->scale);
1426 					d3dvs.p.z = this->pos.z + (vertex + 1)->z + ((vertex->z - (vertex + 1)->z) * this->scale);
1427 
1428 					EE_RT2(&d3dvs, d3dv);
1429 
1430 
1431 					float fRandom	= rnd() * 80.f;
1432 
1433 					col = checked_range_cast<int>(fRandom);
1434 
1435 					if (!arxtime.is_paused()) d3dv->color = Color::grayb(col).toBGR(col);
1436 
1437 					d3dv->uv.x = u;
1438 					d3dv->uv.y = 0.f;
1439 					vertex++;
1440 					d3dv++;
1441 
1442 					d3dvs.p.x = this->pos.x + vertex->x;
1443 					d3dvs.p.y = this->pos.y;
1444 					d3dvs.p.z = this->pos.z + vertex->z;
1445 
1446 					EE_RT2(&d3dvs, d3dv);
1447 
1448 
1449 					fRandom = rnd() * 80.f;
1450 
1451 					col = checked_range_cast<int>(fRandom);
1452 
1453 
1454 					if (!arxtime.is_paused()) d3dv->color = Color::black.toBGR(col);
1455 
1456 					d3dv->uv.x = u;
1457 					d3dv->uv.y = 0.9999999f;
1458 					vertex++;
1459 					d3dv++;
1460 
1461 					u += du;
1462 					nb--;
1463 				}
1464 
1465 				u = ddu;
1466 				du = -du;
1467 			}
1468 
1469 			nbc = 3;
1470 			while(nbc--) {
1471 
1472 				PARTICLE_DEF * pd = createParticle();
1473 				if(!pd) {
1474 					break;
1475 				}
1476 
1477 				float a = radians(360.f * rnd());
1478 				pd->ov = pos + Vec3f(rbase * EEcos(a), 0.f, rbase * EEsin(a));
1479 				float t = fdist(pd->ov, pos);
1480 				pd->move = Vec3f((5.f + 5.f * rnd()) * ((pd->ov.x - pos.x) / t), 3.f * rnd(),
1481 				                 (5.f + 5.f * rnd()) * ((pd->ov.z - pos.z) / t));
1482 				pd->siz = 30.f + 30.f * rnd();
1483 				pd->tolive = 3000;
1484 				pd->timcreation = -(long(arxtime) + 3000l); // TODO WTF
1485 				pd->special = FIRE_TO_SMOKE | FADE_IN_AND_OUT | ROTATING | MODULATE_ROTATION
1486 				              | DISSIPATING;
1487 				pd->fparam = 0.0000001f;
1488 			}
1489 			break;
1490 
1491 		case 1:
1492 			nbc = 2;
1493 
1494 			while (nbc--)
1495 			{
1496 				vertex = this->cone[nbc].conevertex;
1497 				d3dv = this->cone[nbc].coned3d;
1498 				nb = (this->cone[nbc].conenbvertex) >> 1;
1499 
1500 				while (nb)
1501 				{
1502 					d3dvs.p = this->pos + *vertex;
1503 
1504 					EE_RT2(&d3dvs, d3dv);
1505 					col = Random::get(0, 80);
1506 
1507 					if (!arxtime.is_paused()) d3dv->color = Color::grayb(col).toBGR(col);
1508 
1509 					d3dv->uv.x = u;
1510 					d3dv->uv.y = 0.f;
1511 					vertex++;
1512 					d3dv++;
1513 
1514 					d3dvs.p.x = this->pos.x + vertex->x;
1515 					d3dvs.p.y = this->pos.y;
1516 					d3dvs.p.z = this->pos.z + vertex->z;
1517 
1518 					EE_RT2(&d3dvs, d3dv);
1519 					col = Random::get(0, 80);
1520 
1521 					if (!arxtime.is_paused()) d3dv->color = Color::black.toBGR(col);
1522 
1523 					d3dv->uv.x = u;
1524 					d3dv->uv.y = 1;
1525 					vertex++;
1526 					d3dv++;
1527 
1528 					u += du;
1529 					nb--;
1530 				}
1531 
1532 				u = ddu;
1533 				du = -du;
1534 			}
1535 
1536 			nbc = 10;
1537 			while(nbc--) {
1538 
1539 				PARTICLE_DEF * pd = createParticle();
1540 				if(!pd) {
1541 					break;
1542 				}
1543 
1544 				float a = radians(360.f * rnd());
1545 				pd->ov = pos + Vec3f(rbase * EEcos(a), 0.f, rbase * EEsin(a));
1546 				float t = fdist(pd->ov, pos);
1547 				pd->move = Vec3f((5.f + 5.f * rnd()) * ((pd->ov.x - pos.x) / t), 3.f * rnd(),
1548 				                 (5.f + 5.f * rnd()) * ((pd->ov.z - pos.z) / t));
1549 				pd->siz = 30.f + 30.f * rnd();
1550 				pd->tolive = 3000;
1551 				pd->timcreation = -(long(arxtime) + 3000l); // TODO WTF
1552 				pd->special = FIRE_TO_SMOKE | FADE_IN_AND_OUT | ROTATING | MODULATE_ROTATION
1553 				              | DISSIPATING;
1554 				pd->fparam = 0.0000001f;
1555 			}
1556 
1557 			break;
1558 	}
1559 
1560 	//tracé du cone back
1561 	GRenderer->SetBlendFunc(Renderer::BlendOne, Renderer::BlendOne);
1562 	GRenderer->SetRenderState(Renderer::AlphaBlending, true);
1563 	GRenderer->GetTextureStage(0)->SetWrapMode(TextureStage::WrapMirror);
1564 
1565 	GRenderer->SetTexture(0, tsouffle);
1566 
1567 	GRenderer->SetCulling(Renderer::CullCW);
1568 	int i = cone[1].conenbfaces - 2;
1569 	int j = 0;
1570 
1571 	while (i--)
1572 	{
1573 		ARX_DrawPrimitive(&cone[1].coned3d[j],
1574 		                             &cone[1].coned3d[j+1],
1575 		                             &cone[1].coned3d[j+2]);
1576 		j++;
1577 	}
1578 
1579 	i = cone[0].conenbfaces - 2;
1580 	j = 0;
1581 
1582 	while (i--)
1583 	{
1584 		ARX_DrawPrimitive(&cone[0].coned3d[j],
1585 		                             &cone[0].coned3d[j+1],
1586 		                             &cone[0].coned3d[j+2]);
1587 		j++;
1588 	}
1589 
1590 	//tracé du cone front
1591 	GRenderer->SetCulling(Renderer::CullCCW);
1592 
1593 	i = cone[1].conenbfaces - 2;
1594 	j = 0;
1595 
1596 	while (i--)
1597 	{
1598 		ARX_DrawPrimitive(&cone[1].coned3d[j],
1599 		                             &cone[1].coned3d[j+1],
1600 		                             &cone[1].coned3d[j+2]);
1601 		j++;
1602 	}
1603 
1604 	i = cone[0].conenbfaces - 2;
1605 	j = 0;
1606 
1607 	while (i--)
1608 	{
1609 		ARX_DrawPrimitive(&cone[0].coned3d[j],
1610 		                             &cone[0].coned3d[j+1],
1611 		                             &cone[0].coned3d[j+2]);
1612 		j++;
1613 	}
1614 
1615 	//tracé des pierres
1616 	GRenderer->SetBlendFunc(Renderer::BlendSrcAlpha, Renderer::BlendInvSrcAlpha);
1617 	this->DrawStone();
1618 
1619 	GRenderer->SetBlendFunc(Renderer::BlendOne, Renderer::BlendZero);
1620 	GRenderer->SetRenderState(Renderer::AlphaBlending, false);
1621 	GRenderer->SetRenderState(Renderer::DepthWrite, true);
1622 
1623 	return 0;
1624 }
1625