/*
===========================================================================
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_Lvl01.cpp
//////////////////////////////////////////////////////////////////////////////////////
//
// Description:
// ARX Spell FX Level 01
//
// Refer to:
// CSpellFx.h
//
// Copyright (c) 1999-2001 ARKANE Studios SA. All rights reserved
//////////////////////////////////////////////////////////////////////////////////////
#include "ARX_SpellFx_Lvl01.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "ARX_Time.h"
#include "ARX_Npc.h"
#include "ARX_SpellFx_Lvl05.h"
#include
#include
#define new new(_NORMAL_BLOCK,__FILE__, __LINE__)
extern CParticleManager * pParticleManager;
extern long cur_mr;
//-----------------------------------------------------------------------------
void LaunchMagicMissileExplosion(EERIE_3D & _ePos, int t = 0, long spellinstance = -1)
{
// système de partoches pour l'explosion
CParticleSystem * pPS = new CParticleSystem();
CParticleParams cp;
cp.iNbMax = 100 + t * 50;
cp.fLife = 1500;
cp.fLifeRandom = 0;
cp.p3Pos.x = 10;
cp.p3Pos.y = 10;
cp.p3Pos.z = 10;
cp.p3Direction.x = 0;
cp.p3Direction.y = -10;
cp.p3Direction.z = 0;
cp.fAngle = DEG2RAD(360);
cp.fSpeed = 130;
cp.fSpeedRandom = 100;
cp.p3Gravity.x = 0;
cp.p3Gravity.y = 10;
cp.p3Gravity.z = 0;
cp.fFlash = 0;
cp.fRotation = 16;
cp.fStartSize = 5;
cp.fStartSizeRandom = 10;
cp.fEndSize = 0;
cp.fEndSizeRandom = 2;
if ((spellinstance >= 0) && (spells[spellinstance].caster == 0) && (cur_mr == 3))
{
cp.fStartSize = 20;
cp.fSpeed = 13;
cp.fSpeedRandom = 10;
cp.fStartColorRandom[0] = 0;
cp.fStartColorRandom[1] = 0;
cp.fStartColorRandom[2] = 0;
cp.fStartColorRandom[3] = 0;
cp.fStartColor[0] = 0;
cp.fStartColor[1] = 0;
cp.fStartColor[2] = 0;
cp.fStartColor[3] = 0;
cp.fEndColor[0] = 255;
cp.fEndColor[1] = 40;
cp.fEndColor[2] = 120;
cp.fEndColor[3] = 10;//55;
pPS->SetTexture("graph\\particles\\(fx)_mr.bmp", 0, 500);
}
else
{
cp.fStartColorRandom[0] = 100;
cp.fStartColorRandom[1] = 100;
cp.fStartColorRandom[2] = 100;
cp.fStartColorRandom[3] = 100;
cp.fStartColor[0] = 110;
cp.fStartColor[1] = 110;
cp.fStartColor[2] = 110;
cp.fStartColor[3] = 110;
cp.fEndColor[0] = 0;
cp.fEndColor[1] = 0;
cp.fEndColor[2] = 120;
cp.fEndColor[3] = 10;
pPS->SetTexture("graph\\particles\\magicexplosion.bmp", 0, 500);
}
cp.fEndColorRandom[0] = 50;
cp.fEndColorRandom[1] = 50;
cp.fEndColorRandom[2] = 50;
cp.fEndColorRandom[3] = 50;
pPS->SetParams(cp);
pPS->ulParticleSpawn = 0;
EERIE_3D eP;
eP.x = _ePos.x;
eP.y = _ePos.y;
eP.z = _ePos.z;
pPS->SetPos(eP);
pPS->Update(0);
pPS->iParticleNbMax = 0;
long id = GetFreeDynLight();
if (id != -1)
{
DynLight[id].exist = 1;
DynLight[id].intensity = 2.3f;
DynLight[id].fallstart = 250.f;
DynLight[id].fallend = 420.f;
if ((spellinstance >= 0) && (spells[spellinstance].caster == 0) && (cur_mr == 3))
{
DynLight[id].rgb.r = 1.f;
DynLight[id].rgb.g = 0.3f;
DynLight[id].rgb.b = .8f;
}
else
{
DynLight[id].rgb.r = 0.f;
DynLight[id].rgb.g = 0.f;
DynLight[id].rgb.b = .8f;
}
DynLight[id].pos.x = eP.x;
DynLight[id].pos.y = eP.y;
DynLight[id].pos.z = eP.z;
DynLight[id].duration = 1500;
}
if (pParticleManager)
{
pParticleManager->AddSystem(pPS);
}
ARX_SOUND_PlaySFX(SND_SPELL_MM_HIT, &_ePos);
}
//-----------------------------------------------------------------------------
CMagicMissile::CMagicMissile() : CSpellFx()
{
tex_mm = NULL;
bExplo = false;
bMove = true;
}
//-----------------------------------------------------------------------------
CMagicMissile::CMagicMissile(LPDIRECT3DDEVICE7 m_pd3dDevice) : CSpellFx()
{
eSrc.x = 0;
eSrc.y = 0;
eSrc.z = 0;
SetDuration(2000);
ulCurrentTime = ulDuration + 1;
tex_mm = MakeTCFromFile("Graph\\Obj3D\\textures\\(Fx)_bandelette_blue.bmp");
if (!smissile)
{
smissile = _LoadTheObj("Graph\\Obj3D\\Interactive\\Fix_inter\\fx_magic_missile\\fx_magic_missile.teo", NULL);
EERIE_3DOBJ_RestoreTextures(smissile);
}
smissile_count++;
fColor[0] = 1;
fColor[1] = 1;
fColor[2] = 1;
fColor1[0] = 1;
fColor1[1] = 1;
fColor1[2] = 1;
bExplo = false;
bMove = true;
}
//-----------------------------------------------------------------------------
CMagicMissile::~CMagicMissile()
{
smissile_count--;
if (smissile && (smissile_count <= 0))
{
smissile_count = 0;
ReleaseEERIE3DObj(smissile);
smissile = NULL;
}
if (this->lLightId != -1)
{
this->lLightId = -1;
}
ARX_SOUND_Stop(snd_loop);
}
//-----------------------------------------------------------------------------
void CMagicMissile::Create(EERIE_3D aeSrc, EERIE_3D angles)
{
int i;
EERIE_3D s, e;
SetDuration(ulDuration);
SetAngle(angles.b);
Vector_Copy(&this->angles, &angles);
eCurPos.x = eSrc.x = aeSrc.x;
eCurPos.y = eSrc.y = aeSrc.y;
eCurPos.z = eSrc.z = aeSrc.z;
fSize = 1;
bDone = true;
s.x = eSrc.x;
s.y = eSrc.y;
s.z = eSrc.z;
e.x = eSrc.x;
e.y = eSrc.y;
e.z = eSrc.z;
i = 0;
i = 40;
e.x -= fBetaRadSin * 50 * i;
e.y += sin(DEG2RAD(MAKEANGLE(this->angles.a))) * 50 * i;
e.z += fBetaRadCos * 50 * i;
pathways[0].sx = eSrc.x;
pathways[0].sy = eSrc.y;
pathways[0].sz = eSrc.z;
pathways[5].sx = e.x;
pathways[5].sy = e.y;
pathways[5].sz = e.z;
Split(pathways, 0, 5, 50, 0.5f);
for (i = 0; i < 6; i++)
{
if (pathways[i].sy >= eSrc.y + 150)
{
pathways[i].sy = eSrc.y + 150;
}
}
fTrail = 0;
iLength = 50;
fOneOnLength = 1.0f / (float) iLength;
iBezierPrecision = BEZIERPrecision;
fOneOnBezierPrecision = 1.0f / (float) iBezierPrecision;
bExplo = false;
bMove = true;
ARX_SOUND_PlaySFX(SND_SPELL_MM_CREATE, &eCurPos);
ARX_SOUND_PlaySFX(SND_SPELL_MM_LAUNCH, &eCurPos);
snd_loop = ARX_SOUND_PlaySFX(SND_SPELL_MM_LOOP, &eCurPos, 1.0F, ARX_SOUND_PLAY_LOOPED);
}
//-----------------------------------------------------------------------------
void CMagicMissile::SetColor(float faRed, float faGreen, float faBlue)
{
fColor[0] = faRed;
fColor[1] = faGreen;
fColor[2] = faBlue;
}
//-----------------------------------------------------------------------------
void CMagicMissile::SetColor1(float faRed, float faGreen, float faBlue)
{
fColor1[0] = faRed;
fColor1[1] = faGreen;
fColor1[2] = faBlue;
}
//-----------------------------------------------------------------------------
void CMagicMissile::SetTTL(unsigned long aulTTL)
{
unsigned long t = ulCurrentTime;
ulDuration = min(ulCurrentTime + aulTTL, ulDuration);
SetDuration(ulDuration);
ulCurrentTime = t;
// Light
if (lLightId != -1)
{
lLightId = -1;
}
}
//-----------------------------------------------------------------------------
void CMagicMissile::Update(unsigned long aulTime)
{
ARX_SOUND_RefreshPosition(snd_loop, &eCurPos);
ulCurrentTime += aulTime;
}
//-----------------------------------------------------------------------------
float CMagicMissile::Render(LPDIRECT3DDEVICE7 m_pd3dDevice)
{
int i = 0;
EERIE_3D lastpos, newpos;
EERIE_3D v;
EERIE_3D stiteangle;
EERIE_3D stitepos;
EERIE_3D stitescale;
EERIE_RGB stitecolor;
EERIE_3D av;
if (ulCurrentTime >= ulDuration)
{
return 0.f;
}
// Set Appropriate Renderstates -------------------------------------------
SETCULL(m_pd3dDevice, D3DCULL_NONE);
SETZWRITE(m_pd3dDevice, FALSE);
m_pd3dDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_ONE);
m_pd3dDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_ONE);
SETALPHABLEND(m_pd3dDevice, TRUE);
// Set Texture ------------------------------------------------------------
if (tex_mm && tex_mm->m_pddsSurface)
{
if ((spells[spellinstance].caster == 0) && (cur_mr == 3))
SETTC(m_pd3dDevice, NULL);
else
SETTC(m_pd3dDevice, tex_mm);
}
// ------------------------------------------------------------------------
if (bMove)
{
fTrail = (ulCurrentTime * fOneOnDuration) * (iBezierPrecision + 2) * 5;
}
lastpos.x = pathways[0].sx;
lastpos.y = pathways[0].sy;
lastpos.z = pathways[0].sz;
Vector_Copy(&newpos, &lastpos);
for (i = 0; i < 5; i++)
{
int kp = i;
int kpprec = (i > 0) ? kp - 1 : kp ;
int kpsuiv = kp + 1 ;
int kpsuivsuiv = (i < (5 - 2)) ? kpsuiv + 1 : kpsuiv;
for (int toto = 1; toto < iBezierPrecision; toto++)
{
if (fTrail < i * iBezierPrecision + toto) break;
float t = toto * fOneOnBezierPrecision;
float t1 = t;
float t2 = t1 * t1 ;
float t3 = t2 * t1 ;
float f0 = 2.f * t3 - 3.f * t2 + 1.f ;
float f1 = -2.f * t3 + 3.f * t2 ;
float f2 = t3 - 2.f * t2 + t1 ;
float f3 = t3 - t2 ;
float val = pathways[kpsuiv].sx;
float p0 = 0.5f * (val - pathways[kpprec].sx) ;
float p1 = 0.5f * (pathways[kpsuivsuiv].sx - pathways[kp].sx) ;
v.x = f0 * pathways[kp].sx + f1 * val + f2 * p0 + f3 * p1 ;
val = pathways[kpsuiv].sy ;
p0 = 0.5f * (val - pathways[kpprec].sy) ;
p1 = 0.5f * (pathways[kpsuivsuiv].sy - pathways[kp].sy) ;
v.y = f0 * pathways[kp].sy + f1 * val + f2 * p0 + f3 * p1 ;
val = pathways[kpsuiv].sz ;
p0 = 0.5f * (val - pathways[kpprec].sz) ;
p1 = 0.5f * (pathways[kpsuivsuiv].sz - pathways[kp].sz) ;
v.z = f0 * pathways[kp].sz + f1 * val + f2 * p0 + f3 * p1 ;
Vector_Copy(&newpos, &v);
if (!((fTrail - (i * iBezierPrecision + toto)) > iLength))
{
float c;
if (fTrail < iLength)
{
c = 1.0f - ((fTrail - (i * iBezierPrecision + toto)) / fTrail);
}
else
{
c = 1.0f - ((fTrail - (i * iBezierPrecision + toto)) / (float)iLength);
}
float fsize = c;
float alpha = c - 0.2f;
if (alpha < 0.2f) alpha = 0.2f;
c += frand2() * 0.1f;
if (c < 0) c = 0;
else if (c > 1) c = 1;
int color = D3DRGB(c * fColor[0] * alpha, c * fColor[1] * alpha, c * fColor[2] * alpha);
if (fsize < 0.5f)
fsize = fsize * 2 * 3;
else
fsize = (1.0f - fsize + 0.5f) * 2 * (3 * 0.5f);
float fs = fsize * 6 + rnd() * 0.3f;
float fe = fsize * 6 + rnd() * 0.3f;
Draw3DLineTex(m_pd3dDevice, lastpos, newpos, color, fs, fe);
}
EERIE_3D temp_vector;
Vector_Copy(&temp_vector, &lastpos);
Vector_Copy(&lastpos, &newpos);
Vector_Copy(&newpos, &temp_vector);
}
}
av.x = newpos.x - lastpos.x;
av.y = newpos.y - lastpos.y;
av.z = newpos.z - lastpos.z;
float bubu = GetAngle(av.x, av.z, 0, 0);
float bubu1 = GetAngle(av.x, av.y, 0, 0);
Vector_Copy(&stitepos, &lastpos);
stiteangle.b = -RAD2DEG(bubu);
stiteangle.a = 0;
stiteangle.g = -(RAD2DEG(bubu1));
if (av.x < 0)
stiteangle.g -= 90;
if (av.x > 0)
stiteangle.g += 90;
if (stiteangle.g < 0)
stiteangle.g += 360.0f;
if ((spells[spellinstance].caster == 0) && (cur_mr == 3))
{
stitecolor.r = 1.f;
stitecolor.g = 0.f;
stitecolor.b = 0.2f;
}
else
{
stitecolor.r = 0.3f;
stitecolor.g = 0.3f;
stitecolor.b = 0.5f;
}
Vector_Init(&stitescale, 1, 1, 1);
{
if ((smissile))
DrawEERIEObjEx(m_pd3dDevice, smissile, &stiteangle, &stitepos, &stitescale, &stitecolor);
}
Vector_Copy(&eCurPos, &lastpos);
return 1 - 0.5f * rnd();
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
CMultiMagicMissile::CMultiMagicMissile(LPDIRECT3DDEVICE7 m_pd3dDevice, long nbmissiles) : CSpellFx()
{
SetDuration(2000);
uiNumber = nbmissiles;
pTab = NULL;
pTab = new CSpellFx*[uiNumber]();
if (pTab)
{
for (UINT i = 0 ; i < uiNumber ; i++)
{
pTab[i] = NULL;
pTab[i] = new CMagicMissile(m_pd3dDevice);
pTab[i]->spellinstance = this->spellinstance;
}
}
}
//-----------------------------------------------------------------------------
CMultiMagicMissile::~CMultiMagicMissile()
{
for (UINT i = 0 ; i < uiNumber ; i++)
{
if (pTab[i])
{
if (pTab[i]->lLightId != -1)
{
// no need to kill it because it's a duration light !
pTab[i]->lLightId = -1;
}
delete pTab[i];
}
}
delete [] pTab;
}
//-----------------------------------------------------------------------------
void CMultiMagicMissile::Create(EERIE_3D aePos, EERIE_3D angles)
{
long lMax = 0;
if (pTab)
{
float afAlpha = angles.a;
float afBeta = angles.b;
spells[spellinstance].hand_group = GetActionPointIdx(inter.iobj[spells[spellinstance].caster]->obj, "PRIMARY_ATTACH");
if (spells[spellinstance].hand_group != -1)
{
spells[spellinstance].hand_pos.x = inter.iobj[spells[spellinstance].caster]->obj->vertexlist3[spells[spellinstance].hand_group].v.x;
spells[spellinstance].hand_pos.y = inter.iobj[spells[spellinstance].caster]->obj->vertexlist3[spells[spellinstance].hand_group].v.y;
spells[spellinstance].hand_pos.z = inter.iobj[spells[spellinstance].caster]->obj->vertexlist3[spells[spellinstance].hand_group].v.z;
}
if (spells[spellinstance].caster == 0) // player
{
afBeta = player.angle.b;
afAlpha = player.angle.a;
EERIE_3D vector;
vector.x = -EEsin(DEG2RAD(afBeta)) * EEcos(DEG2RAD(afAlpha)) * 60.f;
vector.y = EEsin(DEG2RAD(afAlpha)) * 60.f;
vector.z = EEcos(DEG2RAD(afBeta)) * EEcos(DEG2RAD(afAlpha)) * 60.f;
if (spells[spellinstance].hand_group != -1)
{
aePos.x = spells[spellinstance].hand_pos.x + vector.x;
aePos.y = spells[spellinstance].hand_pos.y + vector.y;
aePos.z = spells[spellinstance].hand_pos.z + vector.z;
}
else
{
aePos.x = player.pos.x - EEsin(DEG2RAD(afBeta)) + vector.x;
aePos.y = player.pos.y + vector.y; //;
aePos.z = player.pos.z + EEcos(DEG2RAD(afBeta)) + vector.z;
}
}
else
{
afAlpha = 0;
afBeta = inter.iobj[spells[spellinstance].caster]->angle.b;
EERIE_3D vector;
vector.x = -EEsin(DEG2RAD(afBeta)) * EEcos(DEG2RAD(afAlpha)) * 60;
vector.y = EEsin(DEG2RAD(afAlpha)) * 60;
vector.z = EEcos(DEG2RAD(afBeta)) * EEcos(DEG2RAD(afAlpha)) * 60;
if (spells[spellinstance].hand_group != -1)
{
aePos.x = spells[spellinstance].hand_pos.x + vector.x;
aePos.y = spells[spellinstance].hand_pos.y + vector.y;
aePos.z = spells[spellinstance].hand_pos.z + vector.z;
}
else
{
aePos.x = inter.iobj[spells[spellinstance].caster]->pos.x + vector.x;
aePos.y = inter.iobj[spells[spellinstance].caster]->pos.y + vector.y;
aePos.z = inter.iobj[spells[spellinstance].caster]->pos.z + vector.z;
}
INTERACTIVE_OBJ * io = inter.iobj[spells[spellinstance].caster];
if (ValidIONum(io->targetinfo))
{
EERIE_3D * p1 = &spells[spellinstance].caster_pos;
EERIE_3D * p2 = &inter.iobj[io->targetinfo]->pos;
afAlpha = -(RAD2DEG(GetAngle(p1->y, p1->z, p2->y, p2->z + TRUEDistance2D(p2->x, p2->z, p1->x, p1->z)))); //alpha entre orgn et dest;
}
else if (ValidIONum(spells[spellinstance].target))
{
EERIE_3D * p1 = &spells[spellinstance].caster_pos;
EERIE_3D * p2 = &inter.iobj[spells[spellinstance].target]->pos;
afAlpha = -(RAD2DEG(GetAngle(p1->y, p1->z, p2->y, p2->z + TRUEDistance2D(p2->x, p2->z, p1->x, p1->z)))); //alpha entre orgn et dest;
}
}
for (UINT i = 0 ; i < uiNumber ; i++)
{
if (pTab[i])
{
EERIE_3D angles;
angles.a = afAlpha;
angles.b = afBeta;
angles.g = 0;
if (i > 0)
{
angles.a += frand2() * 4.0f;
angles.b += frand2() * 6.0f;
}
pTab[i]->Create(aePos, angles);
float fTime = ulDuration + frand2() * 1000.0f;
ARX_CHECK_LONG(fTime);
long lTime = ARX_CLEAN_WARN_CAST_LONG(fTime);
lTime = max(1000, lTime);
lMax = max(lMax, lTime);
CMagicMissile * pMM = (CMagicMissile *)pTab[i];
pMM->SetDuration(lTime);
if ((spells[spellinstance].caster == 0) && (cur_mr == 3))
{
pMM->SetColor(0.9f, 0.2f, 0.5f);
pMM->SetColor1(0.9f, 0.2f, 0.5f);
}
else
{
pMM->SetColor(0.9f + rnd() * 0.1f, 0.9f + rnd() * 0.1f, 0.7f + rnd() * 0.3f);
pMM->SetColor1(0.9f + rnd() * 0.1f, 0.9f + rnd() * 0.1f, 0.7f + rnd() * 0.3f);
}
pTab[i]->lLightId = GetFreeDynLight();
if (pTab[i]->lLightId != -1)
{
EERIE_LIGHT * el = &DynLight[pTab[i]->lLightId];
el->exist = 1;
el->intensity = 0.7f + 2.3f;
el->fallend = 190.f;
el->fallstart = 80.f;
if ((spells[spellinstance].caster == 0) && (cur_mr == 3))
{
el->rgb.r = 1;
el->rgb.g = 0.3f;
el->rgb.b = 0.8f;
}
else
{
el->rgb.r = 0;
el->rgb.g = 0;
el->rgb.b = 1;
}
el->pos.x = pMM->eSrc.x;
el->pos.y = pMM->eSrc.y;
el->pos.z = pMM->eSrc.z;
el->duration = 300;
}
}
}
}
SetDuration(lMax + 1000);
}
//-----------------------------------------------------------------------------
void CMultiMagicMissile::CheckCollision(float _fPlayer_Magic_Level)
{
if (pTab)
{
for (UINT i = 0 ; i < uiNumber ; i++)
{
if (pTab[i])
{
CMagicMissile * pMM = (CMagicMissile *) pTab[i];
if (pMM->bExplo == false)
{
EERIE_SPHERE sphere;
sphere.origin.x = pMM->eCurPos.x;
sphere.origin.y = pMM->eCurPos.y;
sphere.origin.z = pMM->eCurPos.z;
sphere.radius = 10.f;
if ((spellinstance != -1) && (CheckAnythingInSphere(&sphere, spells[spellinstance].caster, CAS_NO_SAME_GROUP)))
{
EERIE_3D eE3D;
eE3D.x = pMM->eCurPos.x;
eE3D.y = pMM->eCurPos.y;
eE3D.z = pMM->eCurPos.z;
LaunchMagicMissileExplosion(pMM->eCurPos, 0, spellinstance);
ARX_NPC_SpawnAudibleSound(&pMM->eCurPos, inter.iobj[spells[spellinstance].caster]);
pMM->SetTTL(1000);
pMM->bExplo = true;
pMM->bMove = false;
if (pMM->lLightId != -1)
{
pMM->lLightId = -1;
}
long ttt = ARX_DAMAGES_GetFree();
if (ttt != -1)
{
damages[ttt].pos.x = pMM->eCurPos.x;
damages[ttt].pos.y = pMM->eCurPos.y;
damages[ttt].pos.z = pMM->eCurPos.z;
damages[ttt].radius = 80.f;
damages[ttt].damages = (4 + spells[spellinstance].caster_level * DIV5) * .8f;
damages[ttt].area = DAMAGE_FULL;
damages[ttt].duration = -1;
damages[ttt].source = spells[spellinstance].caster;
damages[ttt].flags = DAMAGE_FLAG_DONT_HURT_SOURCE;
damages[ttt].type = DAMAGE_TYPE_MAGICAL;
damages[ttt].exist = TRUE;
}
EERIE_RGB rgb;
rgb.r = 0.3f;
rgb.g = 0.3f;
rgb.b = 0.45f;
ARX_PARTICLES_Add_Smoke(&pMM->eCurPos, 0, 6, &rgb);
}
}
}
}
}
}
//-----------------------------------------------------------------------------
void CMultiMagicMissile::Update(unsigned long _ulTime)
{
if (pTab)
{
for (UINT i = 0 ; i < uiNumber ; i++)
{
if (pTab[i])
{
pTab[i]->Update(_ulTime);
}
}
}
}
//-----------------------------------------------------------------------------
float CMultiMagicMissile::Render(LPDIRECT3DDEVICE7 m_pd3dDevice)
{
long nbmissiles = 0;
if (pTab)
{
for (UINT i = 0 ; i < uiNumber ; i++)
{
if (pTab[i])
{
float fa = pTab[i]->Render(m_pd3dDevice);
CMagicMissile * pMM = (CMagicMissile *) pTab[i];
if (pMM->lLightId != -1)
{
EERIE_LIGHT * el = &DynLight[pMM->lLightId];
el->intensity = 0.7f + 2.3f * fa;
el->pos.x = pMM->eCurPos.x;
el->pos.y = pMM->eCurPos.y;
el->pos.z = pMM->eCurPos.z;
el->time_creation = ARXTimeUL();
}
if (pMM->bMove) nbmissiles++;
}
}
}
if (nbmissiles == 0) return -1;
return 1;
}
//-----------------------------------------------------------------------------
// IGNIT
//-----------------------------------------------------------------------------
CIgnit::CIgnit()
{
}
//-----------------------------------------------------------------------------
CIgnit::~CIgnit()
{
this->Kill();
}
//-----------------------------------------------------------------------------
void CIgnit::Kill(void)
{
int nb = this->nblight;
while (nb--)
{
int id = this->tablight[nb].idl;
if (ValidDynLight(id))
DynLight[id].exist = 0;
this->tablight[nb].idl = -1;
}
this->nblight = 0;
}
//-----------------------------------------------------------------------------
void CIgnit::Create(EERIE_3D * posc, float perim, int speed)
{
this->pos = *posc;
this->perimetre = perim;
this->nblight = 0;
this->duration = speed;
this->currduration = 0;
this->key = 0;
int nb = 256;
while (nb--)
{
this->tablight[nb].actif = 0;
this->tablight[nb].idl = -1;
}
this->ChangeTexture(MakeTCFromFile("Graph\\Particles\\fire_hit.bmp"));
this->ChangeRGBMask(1.f, 1.f, 1.f, RGBA_MAKE(255, 200, 0, 255));
}
//-----------------------------------------------------------------------------
void CIgnit::Action(int aiMode)
{
ARX_CHECK_SHORT(aiMode);
short sMode = ARX_CLEAN_WARN_CAST_SHORT(aiMode);
for (int i = 0; i < nblight; i++)
{
GLight[tablight[i].iLightNum]->status = sMode;
if (aiMode == 1)
{
ARX_SOUND_PlaySFX(SND_SPELL_IGNITE, &spells[spellinstance].caster_pos);
}
else if (aiMode == 0)
{
ARX_SOUND_PlaySFX(SND_SPELL_DOUSE, &spells[spellinstance].caster_pos);
}
}
}
//-----------------------------------------------------------------------------
void CIgnit::AddLight(int aiLight)
{
if (ARXPausedTimer) return;
if (this->nblight > 255) return;
this->tablight[this->nblight].actif = 1;
this->tablight[this->nblight].iLightNum = aiLight;
this->tablight[this->nblight].poslight.x = GLight[aiLight]->pos.x;
this->tablight[this->nblight].poslight.y = GLight[aiLight]->pos.y;
this->tablight[this->nblight].poslight.z = GLight[aiLight]->pos.z;
this->tablight[this->nblight].idl = GetFreeDynLight();
if (this->tablight[this->nblight].idl > 0)
{
int id = this->tablight[this->nblight].idl;
EERIE_LIGHT * el = &DynLight[id];
el->exist = 1;
el->intensity = 0.7f + 2.f * rnd();
el->fallend = 400.f;
el->fallstart = 300.f;
el->rgb.r = this->r;
el->rgb.g = this->g;
el->rgb.b = this->b;
el->pos.x = this->tablight[this->nblight].poslight.x;
el->pos.y = this->tablight[this->nblight].poslight.y;
el->pos.z = this->tablight[this->nblight].poslight.z;
}
this->nblight++;
}
//-----------------------------------------------------------------------------
void CIgnit::Update(unsigned long _ulTime)
{
float a;
int nb;
if (this->currduration >= this->duration)
{
this->key++;
}
switch (this->key)
{
case 0:
a = (((float)this->currduration)) / ((float)this->duration);
if (a >= 1.f) a = 1.f;
nb = this->nblight;
while (nb--)
{
if (this->tablight[nb].actif)
{
this->tablight[nb].posfx.x = this->pos.x + a * (this->tablight[nb].poslight.x - this->pos.x);
this->tablight[nb].posfx.y = this->pos.y + a * (this->tablight[nb].poslight.y - this->pos.y);
this->tablight[nb].posfx.z = this->pos.z + a * (this->tablight[nb].poslight.z - this->pos.z);
int id = this->tablight[nb].idl;
if (id > 0)
{
DynLight[id].intensity = 0.7f + 2.f * rnd();
DynLight[id].pos.x = this->tablight[nb].posfx.x;
DynLight[id].pos.y = this->tablight[nb].posfx.y;
DynLight[id].pos.z = this->tablight[nb].posfx.z;
}
}
}
this->interp = a;
break;
}
if (!ARXPausedTimer) this->currduration += _ulTime;
}
//-----------------------------------------------------------------------------
void CDoze::AddLightDoze(int aiLight)
{
if (ARXPausedTimer) return;
if (this->nblight > 255) return;
this->tablight[this->nblight].actif = 1;
this->tablight[this->nblight].iLightNum = aiLight;
this->tablight[this->nblight].poslight.x = GLight[aiLight]->pos.x;
this->tablight[this->nblight].poslight.y = GLight[aiLight]->pos.y;
this->tablight[this->nblight].poslight.z = GLight[aiLight]->pos.z;
this->tablight[this->nblight].idl = -1;
this->nblight++;
}
//-----------------------------------------------------------------------------
float CIgnit::Render(LPDIRECT3DDEVICE7 device)
{
int nb;
switch (this->key)
{
case 0:
if (this->currduration > this->duration) this->key++;
if (!ARXPausedTimer)
{
float unsuri = (1.f - this->interp);
nb = this->nblight;
while (nb--)
{
if ((this->tablight[nb].actif) && (rnd() > .5f))
{
ARX_GenereSpheriqueEtincelles(&this->tablight[nb].posfx, rnd() * 20.f * unsuri, this->tp, this->r, this->g, this->b, this->mask);
}
}
}
break;
default:
break;
}
return 0;
}
//-----------------------------------------------------------------------------
// PORTALS
//-----------------------------------------------------------------------------
void Split(EERIE_3D * v, int a, int b, float yo)
{
if (a != b)
{
int i = (int)((a + b) * 0.5f);
if ((i != a) && (i != b))
{
v[i].x = (v[a].x + v[b].x) * 0.5f + yo * frand2();
v[i].y = (v[a].y + v[b].y) * 0.5f;
v[i].z = (v[a].z + v[b].z) * 0.5f + yo * frand2();
Split(v, a, i, yo * 0.7f);
Split(v, i, b, yo * 0.7f);
}
}
}
//-----------------------------------------------------------------------------
void GenereArcElectrique(EERIE_3D * pos, EERIE_3D * end, EERIE_3D * tabdef, int nbseg)
{
tabdef[0].x = pos->x;
tabdef[0].y = pos->y;
tabdef[0].z = pos->z;
tabdef[nbseg-1].x = end->x;
tabdef[nbseg-1].y = end->y;
tabdef[nbseg-1].z = end->z;
Split(tabdef, 0, nbseg - 1, 20);
}
//-----------------------------------------------------------------------------
void DrawArcElectrique(LPDIRECT3DDEVICE7 m_pd3dDevice, EERIE_3D * tabdef, int nbseg, TextureContainer * tex, float fBeta, int tsp)
{
D3DTLVERTEX v[4];
D3DTLVERTEX v2[4];
long i;
//-------------------------------------------------------------------------
// rendu
// SETTC(m_pd3dDevice,NULL);
SETCULL(m_pd3dDevice, D3DCULL_NONE);
if (tex && tex->m_pddsSurface)
{
SETTC(m_pd3dDevice, tex);
}
v2[0].color = v2[1].color = v2[2].color = v2[3].color = RGBA_MAKE(tsp, tsp, tsp, 255);
float xx;
float zz;
for (i = 0; i < nbseg - 2; i++)
{
EERIE_3D astart;
astart.x = tabdef[i].x;
astart.y = tabdef[i].y;
astart.z = tabdef[i].z;
zz = 5; // size
xx = (float)(5 * cos(DEG2RAD(fBeta)));
float ax = tabdef[i+1].x;
float ay = tabdef[i+1].y;
float az = tabdef[i+1].z;
// version 2 faces
v2[0].tu = 0;
v2[0].tv = 0;
v2[1].tu = 1;
v2[1].tv = 0;
v2[2].tu = 1;
v2[2].tv = 1;
v2[3].tu = 0;
v2[3].tv = 1;
v[0].sx = astart.x;
v[0].sy = astart.y + zz;
v[0].sz = astart.z;
v[1].sx = astart.x;
v[1].sy = astart.y - zz;
v[1].sz = astart.z;
v[2].sx = ax;
v[2].sy = ay - zz;
v[2].sz = az;
v[3].sx = ax;
v[3].sy = ay + zz;
v[3].sz = az;
EE_RT2(&v[0], &v2[0]);
EE_RT2(&v[1], &v2[1]);
EE_RT2(&v[2], &v2[2]);
EE_RT2(&v[3], &v2[3]);
ARX_DrawPrimitive_SoftClippZ(&v2[0],
&v2[1],
&v2[2]);
ARX_DrawPrimitive_SoftClippZ(&v2[0],
&v2[2],
&v2[3]);
zz *= (float) sin(DEG2RAD(fBeta));
v[0].sx = astart.x + xx;
v[0].sy = astart.y;
v[0].sz = astart.z + zz;
v[1].sx = astart.x - xx;
v[1].sy = astart.y;
v[1].sz = astart.z - zz;
v[2].sx = ax - xx;
v[2].sy = ay;
v[2].sz = az - zz;
v[3].sx = ax + xx;
v[3].sy = ay;
v[3].sz = az + zz;
EE_RT2(&v[0], &v2[0]);
EE_RT2(&v[1], &v2[1]);
EE_RT2(&v[2], &v2[2]);
EE_RT2(&v[3], &v2[3]);
ARX_DrawPrimitive_SoftClippZ(&v2[0],
&v2[1],
&v2[2]);
ARX_DrawPrimitive_SoftClippZ(&v2[0],
&v2[2],
&v2[3]);
}
}
/*--------------------------------------------------------------------------*/
CPortal::~CPortal()
{
if (this->sphereind) free((void *)this->sphereind);
if (this->spherevertex) free((void *)this->spherevertex);
if (this->sphered3d) free((void *)this->sphered3d);
int nb = 256;
while (nb--)
{
if (this->tabeclair[nb].seg) free((void *)this->tabeclair[nb].seg);
}
}
//-----------------------------------------------------------------------------
void CPortal::AddNewEclair(EERIE_3D * endpos, int nbseg, int duration, int numpt)
{
if (ARXPausedTimer) return;
int nb = 256;
if ((this->nbeclair > 255) || (nbseg > 256)) return;
short sNbSeg = ARX_CLEAN_WARN_CAST_SHORT(nbseg);
while (nb--)
{
if (!this->tabeclair[nb].actif)
{
this->nbeclair++;
this->tabeclair[nb].actif = 1;
this->tabeclair[nb].duration = duration;
this->tabeclair[nb].currduration = 0;
this->tabeclair[nb].nbseg = sNbSeg;
this->tabeclair[nb].numpt = numpt;
GenereArcElectrique(&this->pos, endpos, this->tabeclair[nb].seg, this->tabeclair[nb].nbseg);
break;
}
}
}
/*--------------------------------------------------------------------------*/
void CPortal::DrawAllEclair(LPDIRECT3DDEVICE7 device)
{
int nb = 256;
while (nb--)
{
if (this->tabeclair[nb].actif)
{
float a;
a = 1.f - ((float)this->tabeclair[nb].currduration / (float)this->tabeclair[nb].duration);
if (a < 0.f) a = 0.f;
DrawArcElectrique(device, this->tabeclair[nb].seg, this->tabeclair[nb].nbseg, this->te, rnd() * 360.f, (int)(255.f * a));
if (!ARXPausedTimer) this->tabeclair[nb].currduration += this->currframe;
if (this->tabeclair[nb].currduration >= this->tabeclair[nb].duration)
{
this->tabeclair[nb].actif = 0;
this->nbeclair--;
}
}
}
}
/*--------------------------------------------------------------------------*/
void CPortal::Update(unsigned long _ulTime)
{
float a;
switch (this->key)
{
case 0:
a = (float)this->currduration / (float)this->duration;
if (a > 1.f)
{
a = 1.f;
this->key++;
}
this->pos.x = this->sphereposdep.x + (this->sphereposend.x - this->sphereposdep.x) * a;
this->pos.y = this->sphereposdep.y + (this->sphereposend.y - this->sphereposdep.y) * a;
this->pos.z = this->sphereposdep.z + (this->sphereposend.z - this->sphereposdep.z) * a;
this->spherealpha = a * .5f;
if (!ARXPausedTimer) this->currduration += _ulTime;
break;
case 1:
this->spherealpha = 0.5f + rnd();
if (this->spherealpha > 1.f) this->spherealpha = 1.f;
this->spherealpha *= .25f;
//getion eclair dans boule
this->currframe = _ulTime;
if (!ARXPausedTimer) this->timeneweclair -= _ulTime;
if (this->timeneweclair <= 0)
{
this->timeneweclair = (int)(100.f + rnd() * 200.f);
EERIE_3D endpos;
int numpt = (int)(rnd() * (float)(this->spherenbpt - 1));
endpos.x = this->spherevertex[numpt].x + this->pos.x;
endpos.y = this->spherevertex[numpt].y + this->pos.y;
endpos.z = this->spherevertex[numpt].z + this->pos.z;
this->AddNewEclair(&endpos, 32, (int)(1000.f + 1000.f * rnd()), numpt);
}
break;
}
if (this->lLightId >= 0)
{
DynLight[this->lLightId].pos.x = this->pos.x;
DynLight[this->lLightId].pos.y = this->pos.y;
DynLight[this->lLightId].pos.z = this->pos.z;
DynLight[this->lLightId].intensity = 0.7f + 2.f * rnd();
}
}
/*--------------------------------------------------------------------------*/
float CPortal::Render(LPDIRECT3DDEVICE7 device)
{
SETALPHABLEND(device, TRUE);
SETZWRITE(device, FALSE);
device->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_ONE);
device->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_ONE);
//calcul sphere
int nb = this->spherenbpt;
D3DTLVERTEX * v = this->sphered3d, d3dvs;
EERIE_3D * pt = this->spherevertex;
int col = RGBA_MAKE(0, (int)(200.f * this->spherealpha), (int)(255.f * this->spherealpha), 255);
while (nb)
{
d3dvs.sx = pt->x + this->pos.x; //pt du bas
d3dvs.sy = pt->y + this->pos.y;
d3dvs.sz = pt->z + this->pos.z;
EE_RTP(&d3dvs, v);
if (!ARXPausedTimer) v->color = col;
v++;
pt++;
nb--;
}
//update les couleurs aux impacts
nb = 256;
while (nb--)
{
if (this->tabeclair[nb].actif)
{
float a;
a = 1.f - ((float)this->tabeclair[nb].currduration / (float)this->tabeclair[nb].duration);
if (a < 0.f) a = 0.f;
if (this->tabeclair[nb].numpt >= 0)
{
int r = (int)((0.f + (255.f - 0.f) * a) * this->spherealpha * 3.f);
if (r > 255) r = 255;
int g = (int)((200.f + (255.f - 200.f) * a) * this->spherealpha * 3.f);
if (g > 255) g = 255;
int b = (int)(255.f * this->spherealpha * 3.f);
if (b > 255) b = 255;
if (!ARXPausedTimer) this->sphered3d[this->tabeclair[nb].numpt].color = RGBA_MAKE(r, g, b, 255);
}
}
}
//affichage de la sphere back
SETCULL(device, D3DCULL_CW);
device->SetTexture(0, NULL);
device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, D3DFVF_TLVERTEX, this->sphered3d, this->spherenbpt, (unsigned short *)this->sphereind, this->spherenbfaces * 3, 0);
//affichage eclair
this->DrawAllEclair(device);
//affichage des particules à l'interieur
if (rnd() > .25f)
{
int j = ARX_PARTICLES_GetFree();
if ((j != -1) && (!ARXPausedTimer))
{
ParticleCount++;
particle[j].exist = 1;
particle[j].zdec = 0;
float a = rnd() * 360.f;
float b = rnd() * 360.f;
float rr = this->r * (rnd() + .25f) * 0.05f;
particle[j].ov.x = this->pos.x;
particle[j].ov.y = this->pos.y;
particle[j].ov.z = this->pos.z;
particle[j].move.x = rr * EEsin(DEG2RAD(a)) * EEcos(DEG2RAD(b));
particle[j].move.y = rr * EEcos(DEG2RAD(a));
particle[j].move.z = rr * EEsin(DEG2RAD(a)) * EEsin(DEG2RAD(b));
particle[j].siz = 10.f;
particle[j].tolive = 1000 + (unsigned long)(float)(rnd() * 1000.f);
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 = tp;
particle[j].special = FADE_IN_AND_OUT | ROTATING | MODULATE_ROTATION | DISSIPATING;
particle[j].fparam = 0.0000001f;
particle[j].r = 1.f;
particle[j].g = 1.f;
particle[j].b = 1.f;
}
}
//affichage de la sphere front
SETCULL(device, D3DCULL_CCW);
device->SetTexture(0, NULL);
device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, D3DFVF_TLVERTEX, this->sphered3d, this->spherenbpt, (unsigned short *)this->sphereind, this->spherenbfaces * 3, 0);
device->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_ONE);
device->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_ZERO);
SETALPHABLEND(device, FALSE);
SETCULL(device, D3DCULL_NONE);
SETZWRITE(device, TRUE);
return 0;
}
/*--------------------------------------------------------------------------*/