/*
===========================================================================
ARX FATALIS GPL Source Code
Copyright (C) 1999-2010 Arkane Studios SA, a ZeniMax Media company.
This file is part of the Arx Fatalis GPL Source Code ('Arx Fatalis Source Code').
Arx Fatalis Source Code is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
Arx Fatalis Source Code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with Arx Fatalis Source Code. If not, see
.
In addition, the Arx Fatalis Source Code is also subject to certain additional terms. You should have received a copy of these
additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Arx
Fatalis Source Code. If not, please request a copy in writing from Arkane Studios at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing Arkane Studios, c/o
ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
//////////////////////////////////////////////////////////////////////////////////////
// @@ @@@ @@@ @@ @@@@@ //
// @@@ @@@@@@ @@@ @@ @@@@ @@@ @@@ //
// @@@ @@@@@@@ @@@ @@@@ @@@@ @@ @@@@ //
// @@@ @@ @@@@ @@@ @@@@@ @@@@@@ @@@ @@@ //
// @@@@@ @@ @@@@ @@@ @@@@@ @@@@@@@ @@@ @ @@@ //
// @@@@@ @@ @@@@ @@@@@@@@ @@@@ @@@ @@@@@ @@ @@@@@@@ //
// @@ @@@ @@ @@@@ @@@@@@@ @@@ @@@ @@@@@@ @@ @@@@ //
// @@@ @@@ @@@ @@@@ @@@@@ @@@@@@@@@ @@@@@@@ @@@ @@@@ //
// @@@ @@@@ @@@@@@@ @@@@@@ @@@ @@@@ @@@ @@@ @@@ @@@@ //
// @@@@@@@@ @@@@@ @@@@@@@@@@ @@@ @@@ @@@ @@@ @@@ @@@@@ //
// @@@ @@@@ @@@@ @@@ @@@@@@@ @@@ @@@ @@@@ @@@ @@@@ @@@@@ //
//@@@ @@@@ @@@@@ @@@ @@@@@@ @@ @@@ @@@@ @@@@@@@ @@@@@ @@@@@ //
//@@@ @@@@@ @@@@@ @@@@ @@@ @@ @@ @@@@ @@@@@@@ @@@@@@@@@ //
//@@@ @@@@ @@@@@@@ @@@@ @@ @@ @@@@ @@@@@ @@@@@ //
//@@@ @@@@ @@@@@@@ @@@@ @@ @@ @@@@ @@@@@ @@ //
//@@@ @@@ @@@ @@@@@ @@ @@@ //
// @@@ @@@ @@ @@ STUDIOS //
//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
// CSpellFx_Lvl03.cpp
//////////////////////////////////////////////////////////////////////////////////////
//
// Description:
// ARX Spell FX Level 03
//
// Refer to:
// CSpellFx.h
//
// Copyright (c) 1999-2001 ARKANE Studios SA. All rights reserved
//////////////////////////////////////////////////////////////////////////////////////
#include "danae.h"
#include
#include
#include
#include
#include
#include
#include "ARX_SpellFx_Lvl05.h"
#include "ARX_SpellFx_Lvl03.h"
#include
#include "ARX_CParticle.h"
#include
#include
#include
#include
#include "ARX_Time.h"
#define new new(_NORMAL_BLOCK,__FILE__, __LINE__)
extern CParticleManager * pParticleManager;
//-----------------------------------------------------------------------------
CFireBall::CFireBall() : CSpellFx()
{
eSrc.x = 0;
eSrc.y = 0;
eSrc.z = 0;
SetDuration(2000);
ulCurrentTime = ulDuration + 1;
bExplo = false;
}
//-----------------------------------------------------------------------------
CFireBall::~CFireBall()
{
}
//-----------------------------------------------------------------------------
void CFireBall::SetTTL(unsigned long aulTTL)
{
unsigned long t = ulCurrentTime;
ulDuration = min(ulCurrentTime + aulTTL, ulDuration);
SetDuration(ulDuration);
ulCurrentTime = t;
list::iterator i;
unsigned long ulCalc = ulDuration - ulCurrentTime ;
ARX_CHECK_LONG(ulCalc);
long ff = ARX_CLEAN_WARN_CAST_LONG(ulCalc);
for (i = pPSSmoke.listParticle.begin(); i != pPSSmoke.listParticle.end(); ++i)
{
CParticle * pP = *i;
if (pP->isAlive())
{
if (pP->ulTime + ff < pP->ulTTL)
{
pP->ulTime = pP->ulTTL - ff;
}
}
}
// Light
if (lLightId != -1)
{
lLightId = -1;
}
}
//-----------------------------------------------------------------------------
void CFireBall::Create(EERIE_3D aeSrc, float afBeta, float afAlpha, float _fLevel)
{
SetDuration(ulDuration);
SetAngle(afBeta);
eSrc.x = aeSrc.x - fBetaRadSin * 60;
eSrc.y = aeSrc.y;
eSrc.z = aeSrc.z + fBetaRadCos * 60;
eMove.x = - fBetaRadSin * 80 * cos(DEG2RAD(MAKEANGLE(afAlpha)));
eMove.y = sin(DEG2RAD(MAKEANGLE(afAlpha))) * 80;
eMove.z = + fBetaRadCos * 80 * cos(DEG2RAD(MAKEANGLE(afAlpha)));
fLevel = _fLevel;
CParticleParams cp;
//FIRE
cp.iNbMax = 200;
cp.fLife = 550;
cp.fLifeRandom = 500;
cp.p3Pos.x = 0;
cp.p3Pos.y = 0;
cp.p3Pos.z = 0;
cp.p3Direction.x = -eMove.x;
cp.p3Direction.y = -eMove.y;
cp.p3Direction.z = -eMove.z;
cp.fAngle = DEG2RAD(3);
cp.fSpeed = 0;
cp.fSpeedRandom = 0;
cp.p3Gravity.x = 0;
cp.p3Gravity.y = 0;
cp.p3Gravity.z = 0;
cp.fFlash = 0;
cp.fRotation = 50;
cp.fStartSize = 1 * _fLevel;
cp.fStartSizeRandom = 2 * _fLevel;
cp.fStartColor[0] = 22;
cp.fStartColor[1] = 30;
cp.fStartColor[2] = 30;
cp.fStartColor[3] = 0;
cp.fStartColorRandom[0] = 22;
cp.fStartColorRandom[1] = 0;
cp.fStartColorRandom[2] = 0;
cp.fStartColorRandom[3] = 2;
cp.fEndSize = 0;
cp.fEndSizeRandom = 2;
cp.fEndColor[0] = 25;
cp.fEndColor[1] = 25;
cp.fEndColor[2] = 0;
cp.fEndColor[3] = 50;
cp.fEndColorRandom[0] = 50;
cp.fEndColorRandom[1] = 0;
cp.fEndColorRandom[2] = 0;
cp.fEndColorRandom[3] = 120;
pPSFire.SetParams(cp);
pPSFire.fParticleFreq = 100.0f;
pPSFire.ulParticleSpawn = 0;
pPSFire.SetTexture("graph\\particles\\fire.bmp", 0, 200);
pPSFire.Update(0);
//FIRE
cp.iNbMax = 20;
cp.fLife = 550;
cp.fLifeRandom = 500;
cp.p3Pos.x = 0;
cp.p3Pos.y = 0;
cp.p3Pos.z = 0;
cp.p3Direction.x = -eMove.x;
cp.p3Direction.y = -eMove.y;
cp.p3Direction.z = -eMove.z;
cp.fAngle = DEG2RAD(3);
cp.fSpeed = 0;
cp.fSpeedRandom = 0;
cp.p3Gravity.x = 0;
cp.p3Gravity.y = 0;
cp.p3Gravity.z = 0;
cp.fFlash = 0;
cp.fRotation = 50;
cp.fStartSize = 1 * _fLevel;
cp.fStartSizeRandom = 2 * _fLevel;
cp.fStartColor[0] = 22;
cp.fStartColor[1] = 30;
cp.fStartColor[2] = 30;
cp.fStartColor[3] = 0;
cp.fStartColorRandom[0] = 22;
cp.fStartColorRandom[1] = 0;
cp.fStartColorRandom[2] = 0;
cp.fStartColorRandom[3] = 2;
cp.fEndSize = 3 * _fLevel;
cp.fEndSizeRandom = 2 * _fLevel;
cp.fEndColor[0] = 25;
cp.fEndColor[1] = 25;
cp.fEndColor[2] = 0;
cp.fEndColor[3] = 0;
cp.fEndColorRandom[0] = 50;
cp.fEndColorRandom[1] = 0;
cp.fEndColorRandom[2] = 0;
cp.fEndColorRandom[3] = 120;
pPSFire2.SetParams(cp);
pPSFire2.fParticleFreq = 20.0f;
pPSFire2.ulParticleSpawn = 0;
pPSFire2.SetTexture("graph\\particles\\fire.bmp", 0, 200);
pPSFire2.Update(0);
// Smoke
cp.iNbMax = 30;
cp.fLife = 2000;
cp.fLifeRandom = 3000;
cp.p3Pos.x = 0;
cp.p3Pos.y = 10;
cp.p3Pos.z = 10;
cp.p3Direction.x = -eMove.x;
cp.p3Direction.y = -eMove.y;
cp.p3Direction.z = -eMove.z;
cp.fAngle = DEG2RAD(9);
cp.fSpeed = 150;
cp.fSpeedRandom = 150;
cp.p3Gravity.x = 0;
cp.p3Gravity.y = -10;
cp.p3Gravity.z = 0;
cp.fFlash = 0;
cp.fRotation = 90;
cp.fStartSize = 0;
cp.fStartSizeRandom = 2;
cp.fStartColor[0] = 70;
cp.fStartColor[1] = 70;
cp.fStartColor[2] = 51;
cp.fStartColor[3] = 50;
cp.fStartColorRandom[0] = 0;
cp.fStartColorRandom[1] = 0;
cp.fStartColorRandom[2] = 0;
cp.fStartColorRandom[3] = 0;
cp.fEndSize = 7 * _fLevel;
cp.fEndSizeRandom = 2 * _fLevel;
cp.fEndColor[0] = 0;
cp.fEndColor[1] = 0;
cp.fEndColor[2] = 0;
cp.fEndColor[3] = 27;
cp.fEndColorRandom[0] = 0;
cp.fEndColorRandom[1] = 0;
cp.fEndColorRandom[2] = 0;
cp.fEndColorRandom[3] = 20;
pPSSmoke.SetParams(cp);
pPSSmoke.ulParticleSpawn = 0;
pPSSmoke.fParticleFreq = 20.0f;
pPSSmoke.SetTexture("graph\\particles\\big_greypouf.bmp", 0, 0);
pPSSmoke.Update(0);
pPSFire.SetPos(eSrc);
pPSFire2.SetPos(eSrc);
pPSSmoke.SetPos(eSrc);
// Light
lLightId = -1;
eCurPos.x = eSrc.x;
eCurPos.y = eSrc.y;
eCurPos.z = eSrc.z;
}
#define MIN_TIME_FIREBALL 2000 //750
//-----------------------------------------------------------------------------
void CFireBall::Update(unsigned long aulTime)
{
ulCurrentTime += aulTime;
if (ulCurrentTime > MIN_TIME_FIREBALL)
{
// smoke en retard
pPSSmoke.SetPos(eCurPos);
pPSSmoke.Update(aulTime);
float titi = aulTime * 0.0045f;
eCurPos.x = eCurPos.x + eMove.x * titi;
eCurPos.y = eCurPos.y + eMove.y * titi;
eCurPos.z = eCurPos.z + eMove.z * titi;
pPSFire.SetPos(eCurPos);
pPSFire.fParticleSpeed = 100;
pPSFire.fParticleSpeedRandom = 200;
pPSFire.p3ParticleGravity.x = -eMove.x * 2;
pPSFire.p3ParticleGravity.y = -eMove.y * 2;
pPSFire.p3ParticleGravity.z = -eMove.z * 2;
pPSFire2.p3ParticleGravity.x = -eMove.x * 2;
pPSFire2.p3ParticleGravity.y = -eMove.y * 2;
pPSFire2.p3ParticleGravity.z = -eMove.z * 2;
pPSFire2.SetPos(eCurPos);
pPSFire2.fParticleSpeed = 100;
pPSFire2.fParticleSpeedRandom = 100;
}
else
{
float afAlpha = 0.f;
if (spells[spellinstance].caster == 0)
{
SetAngle(player.angle.b);
afAlpha = player.angle.a;
long idx = GetGroupOriginByName(inter.iobj[spells[spellinstance].caster]->obj, "CHEST");
if (idx)
{
eCurPos.x = inter.iobj[spells[spellinstance].caster]->obj->vertexlist3[idx].v.x - fBetaRadSin * 60;
eCurPos.y = inter.iobj[spells[spellinstance].caster]->obj->vertexlist3[idx].v.y;
eCurPos.z = inter.iobj[spells[spellinstance].caster]->obj->vertexlist3[idx].v.z + fBetaRadCos * 60;
}
else
{
eCurPos.x = player.pos.x - fBetaRadSin * 60;
eCurPos.y = player.pos.y;
eCurPos.z = player.pos.z + fBetaRadCos * 60;
}
}
else
{
SetAngle(inter.iobj[spells[spellinstance].caster]->angle.b);
eCurPos.x = inter.iobj[spells[spellinstance].caster]->pos.x - fBetaRadSin * 60;
eCurPos.y = inter.iobj[spells[spellinstance].caster]->pos.y;
eCurPos.z = inter.iobj[spells[spellinstance].caster]->pos.z + fBetaRadCos * 60;
if ((ValidIONum(spells[spellinstance].caster))
&& (inter.iobj[spells[spellinstance].caster]->ioflags & IO_NPC))
{
eCurPos.x -= EEsin(DEG2RAD(inter.iobj[spells[spellinstance].caster]->angle.b)) * 30.f;
eCurPos.y -= 80.f;
eCurPos.z += EEcos(DEG2RAD(inter.iobj[spells[spellinstance].caster]->angle.b)) * 30.f;
}
INTERACTIVE_OBJ * io = inter.iobj[spells[spellinstance].caster];
if (ValidIONum(io->targetinfo))
{
EERIE_3D * p1 = &eCurPos;
EERIE_3D p2;
Vector_Copy(&p2, &inter.iobj[io->targetinfo]->pos);
p2.y -= 60.f;
afAlpha = 360.f - (RAD2DEG(GetAngle(p1->y, p1->z, p2.y, p2.z + TRUEDistance2D(p2.x, p2.z, p1->x, p1->z)))); //alpha entre orgn et dest;
}
}
eMove.x = - fBetaRadSin * 100 * cos(DEG2RAD(MAKEANGLE(afAlpha)));
eMove.y = sin(DEG2RAD(MAKEANGLE(afAlpha))) * 100;
eMove.z = + fBetaRadCos * 100 * cos(DEG2RAD(MAKEANGLE(afAlpha)));
EERIE_3D vMove;
float f = 1.f / TRUEVector_Magnitude(&eMove);
vMove.x = eMove.x * f;
vMove.y = eMove.y * f;
vMove.z = eMove.z * f;
// smoke en retard
pPSSmoke.p3ParticleDirection.x = -vMove.x;
pPSSmoke.p3ParticleDirection.y = -vMove.y;
pPSSmoke.p3ParticleDirection.z = -vMove.z;
pPSSmoke.SetPos(eCurPos);
pPSSmoke.RecomputeDirection();
float titi = aulTime * 0.0045f;
eCurPos.x = eCurPos.x + eMove.x * titi;
eCurPos.y = eCurPos.y + eMove.y * titi;
eCurPos.z = eCurPos.z + eMove.z * titi;
pPSFire.p3ParticleDirection.x = -vMove.x;
pPSFire.p3ParticleDirection.y = -vMove.y;
pPSFire.p3ParticleDirection.z = -vMove.z;
pPSFire.RecomputeDirection();
pPSFire.SetPos(eCurPos);
pPSFire.p3ParticleGravity.x = -eMove.x * 2;
pPSFire.p3ParticleGravity.y = -eMove.y * 2;
pPSFire.p3ParticleGravity.z = -eMove.z * 2;
pPSFire2.p3ParticleDirection.x = -vMove.x;
pPSFire2.p3ParticleDirection.y = -vMove.y;
pPSFire2.p3ParticleDirection.z = -vMove.z;
pPSFire2.p3ParticleGravity.x = -eMove.x * 2;
pPSFire2.p3ParticleGravity.y = -eMove.y * 2;
pPSFire2.p3ParticleGravity.z = -eMove.z * 2;
pPSFire2.RecomputeDirection();
pPSFire2.SetPos(eCurPos);
}
pPSFire.Update(aulTime);
pPSFire2.Update(aulTime);
}
//-----------------------------------------------------------------------------
float CFireBall::Render(LPDIRECT3DDEVICE7 m_pd3dDevice)
{
if (ulCurrentTime >= ulDuration)
{
return 0.f;
}
SETCULL(m_pd3dDevice, D3DCULL_NONE);
SETZWRITE(m_pd3dDevice, FALSE);
SETALPHABLEND(m_pd3dDevice, TRUE);
pPSFire.Render(m_pd3dDevice, D3DBLEND_ONE, D3DBLEND_ONE);
pPSFire2.Render(m_pd3dDevice, D3DBLEND_ONE, D3DBLEND_ONE);
pPSSmoke.Render(m_pd3dDevice, D3DBLEND_ONE, D3DBLEND_ONE);
return 1 - 0.5f * rnd();
}
//-----------------------------------------------------------------------------
CIceProjectile::~CIceProjectile()
{
stite_count--;
if (stite && (stite_count <= 0))
{
stite_count = 0;
ReleaseEERIE3DObj(stite);
stite = NULL;
}
smotte_count--;
if (smotte && (smotte_count <= 0))
{
smotte_count = 0;
ReleaseEERIE3DObj(smotte);
smotte = NULL;
}
}
CIceProjectile::CIceProjectile(LPDIRECT3DDEVICE7 m_pd3dDevice)
{
SetDuration(1000);
ulCurrentTime = ulDuration + 1;
iNumber = MAX_ICE;
tex_p1 = MakeTCFromFile("Graph\\Obj3D\\textures\\(Fx)_tsu_blueting.bmp");
tex_p2 = MakeTCFromFile("Graph\\Obj3D\\textures\\(Fx)_tsu_bluepouf.bmp");
if (!stite)
{
stite = _LoadTheObj("Graph\\Obj3D\\Interactive\\Fix_inter\\Stalagmite\\Stalagmite.teo", NULL);
EERIE_3DOBJ_RestoreTextures(stite);
}
stite_count++;
if (!smotte)
{
smotte = _LoadTheObj("Graph\\Obj3D\\Interactive\\Fix_inter\\Stalagmite\\motte.teo", NULL);
EERIE_3DOBJ_RestoreTextures(smotte);
}
smotte_count++;
iMax = MAX_ICE;
fStep = 20;
}
//-----------------------------------------------------------------------------
void CIceProjectile::Create(EERIE_3D aeSrc, float afBeta, float fLevel)
{
iMax = (int)(30 + fLevel * 5.2f);
Create(aeSrc, afBeta);
}
//-----------------------------------------------------------------------------
void CIceProjectile::Create(EERIE_3D aeSrc, float afBeta)
{
SetDuration(ulDuration);
SetAngle(afBeta);
fSize = 1;
float xmin, ymin, zmin;
int i = 0;
EERIE_3D s, e, h;
s.x = aeSrc.x;
s.y = aeSrc.y - 100;
s.z = aeSrc.z;
float fspelldist = ARX_CLEAN_WARN_CAST_FLOAT(iMax * 15);
fspelldist = min(fspelldist, 200);
fspelldist = max(fspelldist, 450);
e.x = aeSrc.x - fBetaRadSin * fspelldist;
e.y = aeSrc.y - 100;
e.z = aeSrc.z + fBetaRadCos * fspelldist;
float fd;
i = iMax;
if (!Visible(&s, &e, NULL, &h))
{
e.x = h.x + fBetaRadSin * 20;
e.y = h.y;
e.z = h.z - fBetaRadCos * 20;
}
fd = Distance3D(s.x, s.y, s.z, e.x, e.y, e.z);
float fCalc = ulDuration * (fd / fspelldist) ;
ARX_CHECK_ULONG(fCalc);
SetDuration(ARX_CLEAN_WARN_CAST_ULONG(fCalc));
float fDist = (fd / fspelldist) * iMax ;
ARX_CHECK_INT(fDist);
i = ARX_CLEAN_WARN_CAST_INT(fDist);
iNumber = i;
int end = iNumber / 2;
tv1a[0].sx = s.x;
tv1a[0].sy = s.y + 100;
tv1a[0].sz = s.z;
tv1a[end].sx = e.x;
tv1a[end].sy = e.y + 100;
tv1a[end].sz = e.z;
Split(tv1a, 0, end, 80, 0.5f, 0, 1, 80, 0.5f);
for (i = 0; i < iNumber; i++)
{
float t = rnd();
if (t < 0.5f)
tType[i] = 0;
else
tType[i] = 1;
tSize[i].x = 0;
tSize[i].y = 0;
tSize[i].z = 0;
tSizeMax[i].x = rnd();
tSizeMax[i].y = rnd() + 0.2f;
tSizeMax[i].z = rnd();
if (tType[i] == 0)
{
xmin = 1.2f;
ymin = 1;
zmin = 1.2f;
}
else
{
xmin = 0.4f;
ymin = 0.3f;
zmin = 0.4f;
}
if (tSizeMax[i].x < xmin)
tSizeMax[i].x = xmin;
if (tSizeMax[i].y < ymin)
tSizeMax[i].y = ymin;
if (tSizeMax[i].z < zmin)
tSizeMax[i].z = zmin;
int iNum = ARX_CLEAN_WARN_CAST_INT(i / 2);
if (tType[i] == 0)
{
tPos[i].x = tv1a[iNum].sx + frand2() * 80;
tPos[i].y = tv1a[iNum].sy;
tPos[i].z = tv1a[iNum].sz + frand2() * 80;
}
else
{
tPos[i].x = tv1a[iNum].sx + frand2() * 40;
tPos[i].y = tv1a[iNum].sy;
tPos[i].z = tv1a[iNum].sz + frand2() * 40;
}
long ttt = ARX_DAMAGES_GetFree();
if (ttt != -1)
{
damages[ttt].pos.x = tPos[i].x;
damages[ttt].pos.y = tPos[i].y;
damages[ttt].pos.z = tPos[i].z;
damages[ttt].radius = 60.f;
damages[ttt].damages = 0.1f * spells[spellinstance].caster_level;
damages[ttt].area = DAMAGE_FULL;
damages[ttt].duration = ulDuration;
damages[ttt].source = spells[spellinstance].caster;
damages[ttt].flags = DAMAGE_FLAG_DONT_HURT_SOURCE;
damages[ttt].type = DAMAGE_TYPE_MAGICAL | DAMAGE_TYPE_COLD;
damages[ttt].exist = TRUE;
}
}
fColor = 1;
}
//---------------------------------------------------------------------
void CIceProjectile::Update(unsigned long aulTime)
{
ulCurrentTime += aulTime;
if (ulDuration - ulCurrentTime < 1000)
{
fColor = (ulDuration - ulCurrentTime) * DIV1000;
for (int i = 0; i < iNumber; i++)
{
tSize[i].y *= fColor;
}
}
}
//---------------------------------------------------------------------
float CIceProjectile::Render(LPDIRECT3DDEVICE7 m_pd3dDevice)
{
int i = 0;
if (ulCurrentTime >= ulDuration) return 0.f;
SETCULL(m_pd3dDevice, D3DCULL_CW);
SETZWRITE(m_pd3dDevice, FALSE);
m_pd3dDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_INVDESTCOLOR);
m_pd3dDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_ONE);
SETALPHABLEND(m_pd3dDevice, TRUE);
iMax = (int)((iNumber * 2) * fOneOnDuration * ulCurrentTime);
if (iMax > iNumber) iMax = iNumber;
for (i = 0; i < iMax; i++)
{
if (tSize[i].x < tSizeMax[i].x)
tSize[i].x += 0.1f;
if (tSize[i].x > tSizeMax[i].x)
tSize[i].x = tSizeMax[i].x;
if (tSize[i].y < tSizeMax[i].y)
tSize[i].y += 0.1f;
if (tSize[i].y < 0)
tSize[i].y = 0;
if (tSize[i].y > tSizeMax[i].y)
tSize[i].y = tSizeMax[i].y;
if (tSize[i].z < tSizeMax[i].z)
tSize[i].z += 0.1f;
if (tSize[i].z > tSizeMax[i].z)
tSize[i].z = tSizeMax[i].z;
EERIE_3D stiteangle;
EERIE_3D stitepos;
EERIE_3D stitescale;
EERIE_RGB stitecolor;
stiteangle.b = (float) cos(DEG2RAD(tPos[i].x)) * 360;
stiteangle.a = 0;
stiteangle.g = 0;
stitepos.x = tPos[i].x;
stitepos.y = tPos[i].y;
stitepos.z = tPos[i].z;
float tt;
tt = tSizeMax[i].y * fColor;
stitecolor.g = stitecolor.r = tt * 0.7f;
stitecolor.b = tt * 0.9f;
if (stitecolor.r > 1) stitecolor.r = 1;
if (stitecolor.g > 1) stitecolor.g = 1;
if (stitecolor.b > 1) stitecolor.b = 1;
stitescale.x = tSize[i].x;
stitescale.y = tSize[i].y;
stitescale.z = tSize[i].z;
if (tType[i] == 0)
DrawEERIEObjEx(m_pd3dDevice, smotte, &stiteangle, &stitepos, &stitescale, &stitecolor);
else
DrawEERIEObjEx(m_pd3dDevice, stite, &stiteangle, &stitepos, &stitescale, &stitecolor);
}
float x, y, z;
//----------------
for (i = 0; i < min(iNumber, iMax + 1); i++)
{
float t = rnd();
if (t < 0.01f)
{
x = tPos[i].x;
y = tPos[i].y;
z = tPos[i].z;
int j = ARX_PARTICLES_GetFree();
if ((j != -1) && (!ARXPausedTimer))
{
ParticleCount++;
particle[j].exist = 1;
particle[j].zdec = 0;
particle[j].ov.x = x + 5.f - rnd() * 10.f;
particle[j].ov.y = y + 5.f - rnd() * 10.f;
particle[j].ov.z = z + 5.f - rnd() * 10.f;
particle[j].move.x = 2.f - 4.f * rnd();
particle[j].move.y = 2.f - 4.f * rnd();
particle[j].move.z = 2.f - 4.f * rnd();
particle[j].siz = 20.f;
float fMin = min(2000 + (rnd() * 2000.f), ulDuration - ulCurrentTime + 500.0f * rnd());
ARX_CHECK_ULONG(fMin);
particle[j].tolive = ARX_CLEAN_WARN_CAST_ULONG(fMin);
particle[j].scale.x = 1.f;
particle[j].scale.y = 1.f;
particle[j].scale.z = 1.f;
particle[j].timcreation = lARXTime;
particle[j].tc = tex_p2;
particle[j].special = FADE_IN_AND_OUT | ROTATING | MODULATE_ROTATION | DISSIPATING;
particle[j].fparam = 0.0000001f;
particle[j].r = 0.7f;
particle[j].g = 0.7f;
particle[j].b = 1.f;
}
}
else if (t > 0.095f)
{
x = tPos[i].x;
y = tPos[i].y - 50;
z = tPos[i].z;
int j = ARX_PARTICLES_GetFree();
if ((j != -1) && (!ARXPausedTimer))
{
ParticleCount++;
particle[j].exist = 1;
particle[j].zdec = 0;
particle[j].ov.x = x + 5.f - rnd() * 10.f;
particle[j].ov.y = y + 5.f - rnd() * 10.f;
particle[j].ov.z = z + 5.f - rnd() * 10.f;
particle[j].move.x = 0;
particle[j].move.y = 2.f - 4.f * rnd();
particle[j].move.z = 0;
particle[j].siz = 0.5f;
float fMin = min(2000 + (rnd() * 1000.f), ulDuration - ulCurrentTime + 500.0f * rnd());
ARX_CHECK_ULONG(fMin);
particle[j].tolive = ARX_CLEAN_WARN_CAST_ULONG(fMin);
particle[j].scale.x = 1.f;
particle[j].scale.y = 1.f;
particle[j].scale.z = 1.f;
particle[j].timcreation = lARXTime;
particle[j].tc = tex_p1;
particle[j].special = FADE_IN_AND_OUT | ROTATING | MODULATE_ROTATION | DISSIPATING;
particle[j].fparam = 0.0000001f;
particle[j].r = 0.7f;
particle[j].g = 0.7f;
particle[j].b = 1.f;
}
}
}
return 1;
}
//-----------------------------------------------------------------------------
// SPEED
//-----------------------------------------------------------------------------
void CSpeed::Create(int numinteractive, int duration)
{
this->key = 1;
this->duration = duration;
this->currduration = 0;
this->num = numinteractive;
this->nbrubandef = 0;
int nb = 2048;
while (nb--)
{
this->truban[nb].actif = 0;
}
nb = (inter.iobj[this->num]->obj)->nbgroups;
if (nb > 256) nb = 256;
EERIE_GROUPLIST * grouplist = inter.iobj[this->num]->obj->grouplist;
nb >>= 1;
while (nb--)
{
float col = 0.05f + (rnd() * 0.05f);
float size = 4.f + (4.f * rnd());
int taille = 8 + (int)(8.f * rnd());
this->AddRubanDef(grouplist->origin, size, taille, col, col, col, 0.f, 0.f, 0.f);
grouplist += 2;
}
this->tp = MakeTCFromFile("Graph\\Particles\\fire.bmp");
}
//-----------------------------------------------------------------------------
void CSpeed::AddRubanDef(int origin, float size, int dec, float r, float g, float b, float r2, float g2, float b2)
{
if (this->nbrubandef > 255) return;
this->trubandef[this->nbrubandef].first = -1;
this->trubandef[this->nbrubandef].origin = origin;
this->trubandef[this->nbrubandef].size = size;
this->trubandef[this->nbrubandef].dec = dec;
this->trubandef[this->nbrubandef].r = r;
this->trubandef[this->nbrubandef].g = g;
this->trubandef[this->nbrubandef].b = b;
this->trubandef[this->nbrubandef].r2 = r2;
this->trubandef[this->nbrubandef].g2 = g2;
this->trubandef[this->nbrubandef].b2 = b2;
this->nbrubandef++;
}
//-----------------------------------------------------------------------------
int CSpeed::GetFreeRuban()
{
int nb = 2048;
while (nb--)
{
if (!this->truban[nb].actif) return nb;
}
return -1;
}
//-----------------------------------------------------------------------------
void CSpeed::AddRuban(int * f, int id, int dec)
{
int num;
num = this->GetFreeRuban();
if (num >= 0)
{
this->truban[num].actif = 1;
this->truban[num].pos.x = inter.iobj[this->num]->obj->vertexlist3[id].v.x;
this->truban[num].pos.y = inter.iobj[this->num]->obj->vertexlist3[id].v.y;
this->truban[num].pos.z = inter.iobj[this->num]->obj->vertexlist3[id].v.z;
if (*f < 0)
{
*f = num;
this->truban[num].next = -1;
}
else
{
this->truban[num].next = *f;
*f = num;
}
int nb = 0, oldnum = num;
while (num != -1)
{
nb++;
oldnum = num;
num = this->truban[num].next;
}
if (oldnum < 0) ARX_CHECK_NO_ENTRY();
if (nb > dec)
{
this->truban[oldnum].actif = 0;
num = *f;
nb -= 2;
while (nb--)
{
num = this->truban[num].next;
}
this->truban[num].next = -1;
}
}
}
//-----------------------------------------------------------------------------
void CSpeed::Update(unsigned long _ulTime)
{
int nb, num;
switch (this->key)
{
case 0:
break;
case 1:
if (ARXPausedTimer) break;
if (this->currduration > this->duration)
{
this->key++;
}
num = 0;
nb = this->nbrubandef;
while (nb--)
{
this->AddRuban(&this->trubandef[num].first, this->trubandef[num].origin, this->trubandef[num].dec);
num++;
}
break;
}
if (!ARXPausedTimer) this->currduration += _ulTime;
}
//-----------------------------------------------------------------------------
void CSpeed::DrawRuban(LPDIRECT3DDEVICE7 device, int num, float size, int dec, float r, float g, float b, float r2, float g2, float b2)
{
int numsuiv;
float dsize = size / (float)(dec + 1);
dsize = 0.f;
int r1 = ((int)(r * 255.f)) << 16;
int g1 = ((int)(g * 255.f)) << 16;
int b1 = ((int)(b * 255.f)) << 16;
int rr2 = ((int)(r2 * 255.f)) << 16;
int gg2 = ((int)(g2 * 255.f)) << 16;
int bb2 = ((int)(b2 * 255.f)) << 16;
int dr = (rr2 - r1) / dec;
int dg = (gg2 - g1) / dec;
int db = (bb2 - b1) / dec;
while (1)
{
numsuiv = this->truban[num].next;
if ((num >= 0) && (numsuiv >= 0))
{
Draw3DLineTex2(device, this->truban[num].pos, this->truban[numsuiv].pos, size, RGBA_MAKE(r1 >> 16, g1 >> 16, b1 >> 16, 0), RGBA_MAKE((r1 + dr) >> 16, (g1 + dg) >> 16, (b1 + db) >> 16, 0));
r1 += dr;
g1 += dg;
b1 += db;
size -= dsize;
}
else
{
break;
}
num = numsuiv;
}
}
//-----------------------------------------------------------------------------
float CSpeed::Render(LPDIRECT3DDEVICE7 device)
{
SETCULL(device, D3DCULL_NONE);
SETALPHABLEND(device, TRUE);
device->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_ONE);
device->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_ONE);
SETTC(device, NULL);
for (int i = 0; i < nbrubandef; i++)
{
this->DrawRuban(device, trubandef[i].first,
trubandef[i].size,
trubandef[i].dec,
trubandef[i].r, trubandef[i].g, trubandef[i].b,
trubandef[i].r2, trubandef[i].g2, trubandef[i].b2) ;
}
SETALPHABLEND(device, FALSE);
device->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_ONE);
device->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_ZERO);
return 0;
}
//-----------------------------------------------------------------------------
CCreateFood::CCreateFood(LPDIRECT3DDEVICE7 m_pd3dDevice)
{
SetDuration(1000);
ulCurrentTime = ulDuration + 1;
pPS = new CParticleSystem();
}
//-----------------------------------------------------------------------------
CCreateFood::~CCreateFood()
{
}
//-----------------------------------------------------------------------------
void CCreateFood::Create()
{
eSrc.x = player.pos.x;
eSrc.y = player.pos.y;
eSrc.z = player.pos.z;
pPS->SetPos(eSrc);
CParticleParams cp;
cp.iNbMax = 350;
cp.fLife = 800;
cp.fLifeRandom = 2000;
cp.p3Pos.x = 100;
cp.p3Pos.y = 200;
cp.p3Pos.z = 100;
cp.p3Direction.x = 0;
cp.p3Direction.y = -10;
cp.p3Direction.z = 0;
cp.fAngle = DEG2RAD(5);
cp.fSpeed = 120;
cp.fSpeedRandom = 84;
cp.p3Gravity.x = 0;
cp.p3Gravity.y = -10;
cp.p3Gravity.z = 0;
cp.fFlash = 0;
cp.fRotation = 80;
cp.fStartSize = 8;
cp.fStartSizeRandom = 8;
cp.fStartColor[0] = 105;
cp.fStartColor[1] = 105;
cp.fStartColor[2] = 20;
cp.fStartColor[3] = 145;
cp.fStartColorRandom[0] = 50;
cp.fStartColorRandom[1] = 50;
cp.fStartColorRandom[2] = 0;
cp.fStartColorRandom[3] = 10;
cp.fEndSize = 6;
cp.fEndSizeRandom = 4;
cp.fEndColor[0] = 20;
cp.fEndColor[1] = 20;
cp.fEndColor[2] = 5;
cp.fEndColor[3] = 0;
cp.fEndColorRandom[0] = 40;
cp.fEndColorRandom[1] = 40;
cp.fEndColorRandom[2] = 0;
cp.fEndColorRandom[3] = 0;
cp.iBlendMode = 0;
pPS->SetParams(cp);
pPS->ulParticleSpawn = PARTICLE_CIRCULAR | PARTICLE_BORDER;
pPS->SetTexture("graph\\particles\\create_food.bmp", 0, 100); //5
fSize = 1;
}
//---------------------------------------------------------------------
void CCreateFood::Update(unsigned long aulTime)
{
ulCurrentTime += aulTime;
//ARX_BEGIN: jycorbel (2010-07-20) - @TBE : dead code
/*
if (ulCurrentTime >= ulDuration)
*/
//ARX_END: jycorbel (2010-07-20)
eSrc.x = inter.iobj[0]->pos.x;
eSrc.y = inter.iobj[0]->pos.y;
eSrc.z = inter.iobj[0]->pos.z;
//ARX_BEGIN: jycorbel (2010-07-20) - Correct bug when this spell is cast, the function update particule after-life
if( ulCurrentTime <= ulDuration ) //ulCalc (time before end spell) must be positive !
//ARX_END: jycorbel (2010-07-20)
{
unsigned long ulCalc = ulDuration - ulCurrentTime ;
ARX_CHECK_LONG(ulCalc);
long ff = ARX_CLEAN_WARN_CAST_LONG(ulCalc);
if (ff < 1500)
{
pPS->uMaxParticles = 0;
pPS->ulParticleSpawn = PARTICLE_CIRCULAR;
pPS->p3ParticleGravity.x = 0;
pPS->p3ParticleGravity.y = 0;
pPS->p3ParticleGravity.z = 0;
list::iterator i;
for (i = pPS->listParticle.begin(); i != pPS->listParticle.end(); ++i)
{
CParticle * pP = *i;
if (pP->isAlive())
{
pP->fColorEnd[3] = 0;
if (pP->ulTime + ff < pP->ulTTL)
{
pP->ulTime = pP->ulTTL - ff;
}
}
}
}
}
pPS->SetPos(eSrc);
pPS->Update(aulTime);
}
//---------------------------------------------------------------------
float CCreateFood::Render(LPDIRECT3DDEVICE7 m_pd3dDevice)
{
pPS->Render(m_pd3dDevice, D3DBLEND_ONE, D3DBLEND_ONE);
return 1;
}