/*
===========================================================================
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 //
//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
// ARX_Particles
//////////////////////////////////////////////////////////////////////////////////////
//
// Description:
// ARX Particles Management
//
// Updates: (date) (person) (update)
//
// Code: Cyril Meynier
//
// Copyright (c) 1999-2000 ARKANE Studios SA. All rights reserved
//////////////////////////////////////////////////////////////////////////////////////
//#include "danae.h"
#include "ARX_Particles.h"
#include "ARX_Input.h"
#include "ARX_CSpellFx.h"
#include "ARX_Sound.h"
#include "ARX_Collisions.h"
#include "ARX_Interface.h" // -> à virer
#include "ARX_Menu2.h"
#include "ARX_MenuPublic.h"
#include "ARX_Paths.h"
#include "ARX_Time.h"
#include "ARX_Damages.h"
#include "ARX_Scene.h"
#include "EERIEMath.h"
#include "EERIEDraw.h"
#include "EERIEObject.h"
#include "EERIEPhysicsBox.h"
extern CMenuConfig *pMenuConfig;
#include
#define _CRTDBG_MAP_ALLOC
#include
extern float fZFogEnd;
extern unsigned long ulBKGColor;
extern bool bSoftRender;
//-----------------------------------------------------------------------------
typedef struct
{
EERIE_3D pos;
EERIE_3D move;
EERIE_3D scale;
EERIE_RGB fade;
EERIE_3DOBJ * obj;
long special;
EERIE_3D spe[8];
EERIE_3D speinc[8];
unsigned long tim_start;
unsigned long duration;
BOOL exist;
long dynlight;
} OBJFX;
FLARETC flaretc;
PARTICLE_DEF particle[MAX_PARTICLES];
BOOM booms[MAX_BOOMS];
FLARES flare[MAX_FLARES];
D3DTLVERTEX g_Lumignon[4];
TextureContainer *bloodsplat[6];
TextureContainer *water_splat[3];
TextureContainer *water_drop[3];
TextureContainer * smokeparticle=NULL;
TextureContainer * bloodsplatter=NULL;
TextureContainer * healing=NULL;
TextureContainer * tzupouf=NULL;
TextureContainer * fire2=NULL;
OBJFX objfx[MAX_OBJFX];
long BoomCount=0;
long flarenum=0;
long ParticleCount=0;
short OPIPOrgb=0;
short PIPOrgb=0;
short shinum=1;
long NewSpell=0;
TextureContainer *GTC;
float ET_R,ET_G,ET_B;
int ET_MASK;
long HIDEMAGICDUST=0;
//-----------------------------------------------------------------------------
long ARX_BOOMS_GetFree()
{
for(long i=0;iexist = TRUE;
pd->zdec = 0;
pd->ov.x = pos->x;
pd->ov.y = pos->y;
pd->ov.z = pos->z;
pd->move.x = 0.f;
pd->move.y = 0.f;
pd->move.z = 0.f;
pd->timcreation = lARXTime;
pd->tolive = (unsigned long)(500.0F + rnd() * 400.0F);
long num = (long)(rnd() * 10.f);
if (num<1) num = 1;
if (num>9) num = 9;
pd->tc = flaretc.shine[num];
pd->siz = 4.f+rnd()*2.f;
pd->scale.x = -15.f;
pd->scale.y = -15.f;
pd->scale.z = -15.f;
pd->r = (float)r*DIV64;
pd->g = (float)g*DIV64;
pd->b = (float)b*DIV64;
pd->special = ROTATING | MODULATE_ROTATION | FADE_IN_AND_OUT | FOLLOW_SOURCE;
pd->fparam = 0.001f;
pd->source = pos;
pd->sourceionum = num;
}
}
//-----------------------------------------------------------------------------
void LaunchDummyParticle()
{
long j=ARX_PARTICLES_GetFree();
if ( (j!=-1)
&& (!ARXPausedTimer) )
{
ParticleCount++;
PARTICLE_DEF * pd=&particle[j];
pd->exist=TRUE;
pd->zdec=0;
float f=DEG2RAD(player.angle.b);
pd->ov.x = player.pos.x+EEsin(f)*100.f;
pd->ov.y = player.pos.y;
pd->ov.z = player.pos.z-EEcos(f)*100.f;
pd->move.x = 0.f;
pd->move.y = 0.f;
pd->move.z = 0.f;
pd->timcreation = lARXTime;
pd->tolive = 600;
pd->tc = smokeparticle;
pd->siz = 15.f;
pd->scale.x = -15.f+rnd()*5.f;
pd->scale.y = -15.f+rnd()*5.f;
pd->scale.z = -15.f+rnd()*5.f;
pd->special = FIRE_TO_SMOKE;
}
}
//-----------------------------------------------------------------------------
void ARX_PARTICLES_Spawn_Lava_Burn(EERIE_3D * poss,float power,INTERACTIVE_OBJ * io)
{
EERIE_3D pos;
pos.x=poss->x;
pos.y=poss->y;
pos.z=poss->z;
if ( (io)
&& (io->obj)
&& (io->obj->nbfaces) )
{
long notok = 10;
long num = 0;
while ( notok-- )
{
F2L( (float)( rnd() * (float)io->obj->nbfaces ), &num );
if ( ( num >= 0 ) && ( num < io->obj->nbfaces ) )
{
if ( io->obj->facelist[num].facetype & POLY_HIDE ) continue;
if ( EEfabs( pos.y-io->obj->vertexlist3[io->obj->facelist[num].vid[0]].v.y ) > 50.f )
continue;
notok = 0;
}
}
if ((notok >= 0) &&
( notok < 10 ) )
{
EERIE_3D * v = &io->obj->vertexlist3[io->obj->facelist[num].vid[0]].v;
pos.x = v->x;
pos.y = v->y;
pos.z = v->z;
}
}
long j = ARX_PARTICLES_GetFree();
if ( ( j != -1 )
&& ( !ARXPausedTimer ) )
{
ParticleCount++;
PARTICLE_DEF * pd = &particle[j];
pd->exist = TRUE;
pd->zdec = 0;
pd->ov.x = pos.x;
pd->ov.y = pos.y;
pd->ov.z = pos.z;
pd->move.x = rnd() * 2 - 4.f;
pd->move.y = rnd() * - 12.f - 15;
pd->move.z = rnd() * 2 - 4.f;
pd->timcreation = lARXTime;
pd->tolive = 800;
pd->tc = smokeparticle;
pd->siz = 15.f;
pd->scale.x = 15.f + rnd() * 5.f;
pd->scale.y = 15.f + rnd() * 5.f;
pd->scale.z = 15.f + rnd() * 5.f;
pd->special = FIRE_TO_SMOKE;
if ( rnd() > 0.5f ) pd->special |= SUBSTRACT;
}
}
extern long GORE_MODE;
//-----------------------------------------------------------------------------
void ARX_PARTICLES_Spawn_Rogue_Blood(EERIE_3D * pos,float dmgs,D3DCOLOR col)
{
long j = ARX_PARTICLES_GetFree();
if ( (j!=-1)
&& (!ARXPausedTimer) )
{
float power;
power=(dmgs*DIV60)+0.9f;
float r,g,b;
r=(float)((long)((col>>16) & 255))*DIV255;
g=(float)((long)((col>>8) & 255))*DIV255;
b=(float)((long)((col) & 255))*DIV255;
ParticleCount++;
PARTICLE_DEF * pd=&particle[j];
pd->exist=TRUE;
pd->zdec=0;
pd->ov.x=pos->x;
pd->ov.y=pos->y;
pd->ov.z=pos->z;
pd->siz = 3.1f*power;
pd->scale.z = pd->scale.y = pd->scale.x = -pd->siz*DIV4;
pd->timcreation = lARXTime;
pd->special = PARTICLE_SUB2 | SUBSTRACT | GRAVITY | ROTATING | MODULATE_ROTATION;
pd->special |= SPLAT_GROUND;
pd->tolive = 1600;
pd->delay = 0;
pd->move.x = rnd()*60.f-30.f;
pd->move.y = rnd()*-10.f-15.f;
pd->move.z = rnd()*60.f-30.f;
pd->r = r;
pd->g = g;
pd->b = b;
long num;
F2L((float)(rnd()*6.f),&num);
if (num<0) num=0;
else if (num>5) num=5;
pd->tc=bloodsplat[num];
pd->fparam=rnd()*DIV10-0.05f;
}
}
//-----------------------------------------------------------------------------
void ARX_PARTICLES_Spawn_Blood3(EERIE_3D * pos,float dmgs,D3DCOLOR col,long vert,INTERACTIVE_OBJ * io,long flags)
{
long j = ARX_PARTICLES_GetFree();
if ( (j!=-1)
&& (!ARXPausedTimer) )
{
float power;
power=(dmgs*DIV60)+0.9f;
float r,g,b;
r=(float)((long)((col>>16) & 255))*DIV255;
g=(float)((long)((col>>8) & 255))*DIV255;
b=(float)((long)((col) & 255))*DIV255;
ParticleCount++;
PARTICLE_DEF * pd=&particle[j];
pd->exist=TRUE;
pd->zdec=0;
pd->ov.x = pos->x - EEsin((float)ARXTime * DIV1000) * 30.f;
pd->ov.y = pos->y + EEsin((float)ARXTime * DIV1000) * 30.f;
pd->ov.z = pos->z + EEcos((float)ARXTime * DIV1000) * 30.f;
pd->siz = 3.5f * power + EEsin((float)ARXTime * DIV1000);
if (!GORE_MODE)
pd->siz*=DIV6;
pd->scale.z = pd->scale.y = pd->scale.x = -pd->siz * DIV2;
pd->timcreation = lARXTime;
pd->special = PARTICLE_SUB2 | SUBSTRACT | GRAVITY | ROTATING | MODULATE_ROTATION;
if (flags & 1)
pd->special|=SPLAT_GROUND;
pd->tolive = 1100;
pd->delay=0;
pd->move.x=0;
pd->move.y=0;
pd->move.z=0;
pd->r=r;
pd->g=g;
pd->b=b;
pd->tc=bloodsplatter;
pd->fparam=rnd()*DIV10-0.05f;
}
if (rnd()>0.90f) ARX_PARTICLES_Spawn_Rogue_Blood(pos,dmgs,col);
}
#define SPLAT_MULTIPLY 1.f
//-----------------------------------------------------------------------------
void ARX_POLYSPLAT_Add(EERIE_3D * poss,long type,EERIE_RGB * col,float size,long flags)
{
if (BoomCount > (MAX_POLYBOOM >> 2) - 30) return;
if ((BoomCount>250.f)
&& (size<10)) return;
float splatsize=90;
if (size>40.f) size=40.f;
size*=0.75f;
if ((!GORE_MODE) && (!(flags & 2)))
size*=DIV5;
switch (pMenuConfig->iLevelOfDetails)
{
case 2:
if (BoomCount>160.f) return;
splatsize=90;
size*=1.f;
break;
case 1:
if (BoomCount>60.f) return;
splatsize=60;
size*=0.5f;
break;
default:
if (BoomCount>10.f) return;
splatsize=30;
size*=0.25f;
break;
}
float py;
EERIEPOLY * ep=CheckInPoly(poss->x,poss->y-40,poss->z,&py);
if (!ep) return;
if (flags & 1) py=poss->y;
EERIEPOLY TheoricalSplat; // clockwise
TheoricalSplat.v[0].sx=-splatsize*SPLAT_MULTIPLY;
TheoricalSplat.v[0].sy = py;
TheoricalSplat.v[0].sz=-splatsize*SPLAT_MULTIPLY;
TheoricalSplat.v[1].sx=-splatsize*SPLAT_MULTIPLY;
TheoricalSplat.v[1].sy = py;
TheoricalSplat.v[1].sz=+splatsize*SPLAT_MULTIPLY;
TheoricalSplat.v[2].sx=+splatsize*SPLAT_MULTIPLY;
TheoricalSplat.v[2].sy = py;
TheoricalSplat.v[2].sz=+splatsize*SPLAT_MULTIPLY;
TheoricalSplat.v[3].sx=+splatsize*SPLAT_MULTIPLY;
TheoricalSplat.v[3].sy = py;
TheoricalSplat.v[3].sz=-splatsize*SPLAT_MULTIPLY;
TheoricalSplat.type=POLY_QUAD;
EERIE_3D RealSplatStart;
RealSplatStart.x=-size;
RealSplatStart.y=py;
RealSplatStart.z=-size;
TheoricalSplat.v[0].sx+=poss->x;
TheoricalSplat.v[0].sz+=poss->z;
TheoricalSplat.v[1].sx+=poss->x;
TheoricalSplat.v[1].sz+=poss->z;
TheoricalSplat.v[2].sx+=poss->x;
TheoricalSplat.v[2].sz+=poss->z;
TheoricalSplat.v[3].sx+=poss->x;
TheoricalSplat.v[3].sz+=poss->z;
RealSplatStart.x+=poss->x;
RealSplatStart.z+=poss->z;
float hdiv,vdiv;
hdiv=vdiv=1.f/(size*2);
long x0,x1;
long z0,z1,i,j;
unsigned long tim;
long n;
EERIE_BKG_INFO * eg;
tim = ARXTimeUL();
for (i=0;ix*ACTIVEBKG->Xmul),&x0);
F2L((poss->z*ACTIVEBKG->Zmul),&z0);
x1 = x0 + 3;
x0 = x0 - 3;
z1 = z0 + 3;
z0 = z0 - 3;
if (x0<0) x0=0;
if (x0>=ACTIVEBKG->Xsize) x0=ACTIVEBKG->Xsize-1;
if (x1<0) x1=0;
if (x1>=ACTIVEBKG->Xsize) x1=ACTIVEBKG->Xsize-1;
if (z0<0) z0=0;
if (z0>=ACTIVEBKG->Zsize) z0=ACTIVEBKG->Zsize-1;
if (z1<0) z1=0;
if (z1>=ACTIVEBKG->Zsize) z1=ACTIVEBKG->Zsize-1;
long nbvert;
float vratio=size*DIV40;
ARX_CHECK_SHORT(z0);
ARX_CHECK_SHORT(x0);
ARX_CHECK_SHORT(z1);
ARX_CHECK_SHORT(x1);
for (j=z0;j<=z1;j++)
for (i=x0;i<=x1;i++)
{
eg=(EERIE_BKG_INFO *)&ACTIVEBKG->Backg[i+j*ACTIVEBKG->Xsize];
for (long l = 0; l < eg->nbpolyin; l++)
{
ep = eg->polyin[l];
if (flags & 2)
{
if (!(ep->type & POLY_WATER)) continue;
}
if ((ep->type & POLY_TRANS) && !(ep->type & POLY_WATER)) continue;
if (ep->type & POLY_QUAD) nbvert=4;
else nbvert=3;
long oki=0;
for (long k=0;kv[k].sx, ep->v[k].sz))
&& (EEfabs(ep->v[k].sy-py)<100.f) )
{
oki=1;
break;
}
if ((PointIn2DPolyXZ(&TheoricalSplat, (ep->v[k].sx+ep->center.x)*DIV2, (ep->v[k].sz+ep->center.z)*DIV2))
&& (EEfabs(ep->v[k].sy-py)<100.f) )
{
oki=1;
break;
}
}
if (!oki && (PointIn2DPolyXZ(&TheoricalSplat, ep->center.x, ep->center.z))
&& (EEfabs(ep->center.y-py)<100.f) )
oki=1;
if (oki)
{
n=ARX_BOOMS_GetFree();
if (n>=0)
{
BoomCount++;
POLYBOOM * pb=&polyboom[n];
pb->type=1;
if (flags & 2)
pb->type=2;
pb->exist=1;
pb->ep=ep;
long num;
F2L((float)(rnd()*6.f),&num);
if (num<0) num=0;
else if (num>5) num=5;
pb->tc=bloodsplat[num];
float fRandom = rnd()*2;
ARX_CHECK_INT(fRandom);
int t = ARX_CLEAN_WARN_CAST_INT(fRandom);
if (flags & 2)
pb->tc = water_splat[t];
pb->tolive=(long)(float)(16000*vratio);
if (flags & 2)
pb->tolive=1500;
pb->timecreation=tim;
pb->tx=ARX_CLEAN_WARN_CAST_SHORT(i);
pb->tz=ARX_CLEAN_WARN_CAST_SHORT(j);
pb->rgb.r=col->r;
pb->rgb.g=col->g;
pb->rgb.b=col->b;
for (int k=0;kv[k].sy-RealSplatStart.y);
pb->u[k]=(ep->v[k].sx-RealSplatStart.x)*hdiv;
if (pb->u[k]<0.5f)
pb->u[k]-=vdiff*hdiv;
else pb->u[k]+=vdiff*hdiv;
pb->v[k]=(ep->v[k].sz-RealSplatStart.z)*vdiv;
if (pb->v[k]<0.5f)
pb->v[k]-=vdiff*vdiv;
else pb->v[k]+=vdiff*vdiv;
}
pb->nbvert=(short)nbvert;
}
}
}
}
}
//-----------------------------------------------------------------------------
void SpawnGroundSplat(EERIE_SPHERE * sp,EERIE_RGB * rgb,float size,long flags)
{
ARX_POLYSPLAT_Add(&sp->origin,0,rgb,size,flags);
}
long TOTAL_BODY_CHUNKS_COUNT=0;
//-----------------------------------------------------------------------------
void ARX_PARTICLES_Spawn_Blood2(EERIE_3D * pos,float dmgs,D3DCOLOR col,long vert,INTERACTIVE_OBJ * io)
{
if ( (io)
&& (io->ioflags & IO_NPC)
&& (io->_npcdata->SPLAT_TOT_NB) )
{
if (io->_npcdata->SPLAT_DAMAGES<3) return;
float power;
power=((float)(io->_npcdata->SPLAT_DAMAGES)*DIV60)+0.9f;
EERIE_3D vect;
vect.x=pos->x-io->_npcdata->last_splat_pos.x;
vect.y=pos->y-io->_npcdata->last_splat_pos.y;
vect.z=pos->z-io->_npcdata->last_splat_pos.z;
float dist=TRUEVector_Magnitude(&vect);
float div=1.f/dist;
vect.x*=div;
vect.y*=div;
vect.z*=div;
long nb;
F2L((float)(dist/(4.f*power)),&nb);
if (nb==0) nb=1;
long MAX_GROUND_SPLATS;
switch (pMenuConfig->iLevelOfDetails)
{
case 2:
MAX_GROUND_SPLATS=10;
break;
case 1:
MAX_GROUND_SPLATS=5;
break;
default:
MAX_GROUND_SPLATS=1;
break;
}
for (long k=0;k_npcdata->last_splat_pos.x+vect.x*(float)k*4.f*power;
posi.y=io->_npcdata->last_splat_pos.y+vect.y*(float)k*4.f*power;
posi.z=io->_npcdata->last_splat_pos.z+vect.z*(float)k*4.f*power;
io->_npcdata->SPLAT_TOT_NB++;
if (io->_npcdata->SPLAT_TOT_NB>MAX_GROUND_SPLATS)
{
ARX_PARTICLES_Spawn_Blood3(&posi,io->_npcdata->SPLAT_DAMAGES,col,vert,io,1);
io->_npcdata->SPLAT_TOT_NB=1;
}
else ARX_PARTICLES_Spawn_Blood3(&posi,io->_npcdata->SPLAT_DAMAGES,col,vert,io,0);
}
}
else
{
if ( (io)
&& (io->ioflags & IO_NPC) )
io->_npcdata->SPLAT_DAMAGES=(short)dmgs;
ARX_PARTICLES_Spawn_Blood3(pos,dmgs,col,vert,io,1);
if ( (io)
&& (io->ioflags & IO_NPC) )
io->_npcdata->SPLAT_TOT_NB=1;
}
if ( (io)
&& (io->ioflags & IO_NPC) )
Vector_Copy(&io->_npcdata->last_splat_pos,pos);
}
//-----------------------------------------------------------------------------
void ARX_PARTICLES_Spawn_Blood(EERIE_3D * pos,EERIE_3D * vect,float dmgs,long source)
{
if (source<0) return;
float nearest_dist=999999999.f;
long nearest=-1;
long count=inter.iobj[source]->obj->nbgroups;
for (long i=0;iobj->vertexlist3[inter.iobj[source]->obj->grouplist[i].origin].v);
if (dist26) spawn_nb=26;
long totdelay=0;
if (nearest>=0)
for (long k=0;kexist=TRUE;
pd->zdec=0;
pd->siz=0.f;
pd->scale.x=(float)spawn_nb;
pd->scale.y=(float)spawn_nb;
pd->scale.z=(float)spawn_nb;
pd->timcreation = lARXTime;
pd->special = GRAVITY | ROTATING | MODULATE_ROTATION | DELAY_FOLLOW_SOURCE;
pd->source = &inter.iobj[source]->obj->vertexlist3[nearest].v;
pd->sourceionum = source;
pd->tolive = 1200+spawn_nb*5;
totdelay += (long)(45.f + rnd() * (150.f - spawn_nb));
pd->delay = totdelay;
pd->r = 0.9f;
pd->g = 0.f;
pd->b = 0.f;
pd->tc = bloodsplatter;
pd->fparam = rnd()*DIV10-0.05f;
}
}
}
long SPARK_COUNT=0;
//-----------------------------------------------------------------------------
// flag & 1 punch failed
// flag & 2 punch success
//-----------------------------------------------------------------------------
void ARX_PARTICLES_Spawn_Spark(EERIE_3D * pos,float dmgs,long flags)
{
if (!pos) return;
long spawn_nb;
F2L(dmgs,&spawn_nb);
if (SPARK_COUNT<1000)
{
SPARK_COUNT+=spawn_nb*25;
}
else
{
SPARK_COUNT -= ARX_CLEAN_WARN_CAST_LONG(FrameDiff);
return;
}
for (long k=0;kexist=TRUE;
pd->zdec=0;
pd->oldpos.x=pd->ov.x=pos->x+rnd()*10.f-5.f;
pd->oldpos.y=pd->ov.y=pos->y+rnd()*10.f-5.f;
pd->oldpos.z=pd->ov.z=pos->z+rnd()*10.f-5.f;
pd->siz = 2.f;
pd->move.x = 6 - 12.f * rnd();
pd->move.y = 6 - 12.f * rnd();
pd->move.z = 6 - 12.f * rnd();
pd->timcreation = lARXTime;
pd->special = PARTICLE_SPARK;
float len = (float)spawn_nb*DIV3;
if ( len > 8 ) len = 8;
if ( len < 3 ) len = 3;
pd->tolive = (unsigned long)(float)(len * 90 + (float)spawn_nb);
if (flags==0)
{
pd->r=0.3f;
pd->g=0.3f;
pd->b=0.f;
}
else if (flags & 1)
{
pd->r=0.2f;
pd->g=0.2f;
pd->b=0.1f;
}
else if (flags & 2)
{
pd->r=0.45f;
pd->g=0.1f;
pd->b=0.f;
}
pd->tc=NULL;
pd->fparam = len + rnd() * len; // Spark Tail Length
}
}
}
//-----------------------------------------------------------------------------
void MakeCoolFx(EERIE_3D * pos)
{
ARX_BOOMS_Add(pos,1);
}
//-----------------------------------------------------------------------------
void MakePlayerAppearsFX(INTERACTIVE_OBJ * io)
{
if (io)
{
MakeCoolFx(&io->pos);
MakeCoolFx(&io->pos);
AddRandomSmoke(io,30);
ARX_PARTICLES_Add_Smoke(&io->pos,1 | 2,20); // flag 1 = randomize pos
}
}
//-----------------------------------------------------------------------------
void AddRandomSmoke(INTERACTIVE_OBJ * io,long amount)
{
if (!io) return;
while (amount--)
{
long num;
F2L(rnd()*((io->obj->nbvertex>>2)-1),&num);
num=(num<<2)+1;
long j=ARX_PARTICLES_GetFree();
if ( (j!=-1)
&& (!ARXPausedTimer) )
{
ParticleCount++;
PARTICLE_DEF * pd=&particle[j];
pd->exist = TRUE;
pd->zdec = 0;
pd->ov.x = io->obj->vertexlist3[num].v.x+rnd()*10.f-5.f;
pd->ov.y = io->obj->vertexlist3[num].v.y+rnd()*10.f-5.f;
pd->ov.z = io->obj->vertexlist3[num].v.z+rnd()*10.f-5.f;
pd->siz = rnd()*8.f;
if (pd->siz<4.f) pd->siz=4.f;
pd->scale.x = 10.f;
pd->scale.y = 10.f;
pd->scale.z = 10.f;
pd->timcreation = lARXTime;
pd->special = ROTATING | MODULATE_ROTATION | FADE_IN_AND_OUT;
pd->tolive = 900+(unsigned long)(rnd()*400.f);
pd->move.x = 0.25f-0.5f*rnd();
pd->move.y = -1.f*rnd()+0.3f;
pd->move.z = 0.25f-0.5f*rnd();
pd->r = 0.3f;
pd->g = 0.3f;
pd->b = 0.34f;
pd->tc = smokeparticle;//tc2;
pd->fparam = 0.001f;//-rnd()*0.0002f;
}
}
}
//-----------------------------------------------------------------------------
void ARX_PARTICLES_Add_Smoke(EERIE_3D * pos,long flags,long amount,EERIE_RGB * rgb) // flag 1 = randomize pos
{
EERIE_3D mod;
mod.x = mod.y = mod.z = 0.f;
if (flags & 1)
{
mod.x=rnd()*100.f-50.f;
mod.y=rnd()*100.f-50.f;
mod.z=rnd()*100.f-50.f;
}
while(amount)
{
amount--;
long j=ARX_PARTICLES_GetFree();
if ( (j!=-1)
&& (!ARXPausedTimer) )
{
ParticleCount++;
PARTICLE_DEF * pd=&particle[j];
pd->exist=TRUE;
pd->zdec=0;
pd->ov.x=pos->x+mod.x;
pd->ov.y=pos->y+mod.y;
pd->ov.z=pos->z+mod.z;
if (flags & 2)
{
pd->siz=rnd()*20.f+15.f;
pd->scale.x=40.f+rnd()*15;
pd->scale.y=40.f+rnd()*15;
pd->scale.z=40.f+rnd()*15;
}
else
{
pd->siz=rnd()*8.f+5.f;
if (pd->siz<4.f) pd->siz=4.f;
pd->scale.x=10.f+rnd()*5;
pd->scale.y=10.f+rnd()*5;
pd->scale.z=10.f+rnd()*5;
}
pd->timcreation = lARXTime;
pd->special = ROTATING | MODULATE_ROTATION | FADE_IN_AND_OUT;
pd->tolive = 1100+(unsigned long)(rnd()*400.f);
pd->delay = (unsigned long)(amount * 120.0F + rnd() * 100.0F);
pd->move.x = 0.25f-0.5f*rnd();
pd->move.y = -1.f*rnd()+0.3f;
pd->move.z = 0.25f-0.5f*rnd();
if (rgb)
{
pd->r = rgb->r;
pd->g = rgb->g;
pd->b = rgb->b;
}
else
{
pd->r=0.3f;
pd->g=0.3f;
pd->b=0.34f;
}
pd->tc = smokeparticle;
pd->fparam = 0.01f;
}
}
}
extern long cur_mr;
//-----------------------------------------------------------------------------
void ManageTorch()
{
EERIE_LIGHT * el=&DynLight[0];
if (SHOW_TORCH)
{
float rr=rnd();
el->pos.x = player.pos.x;
el->pos.y=player.pos.y;
el->pos.z = player.pos.z;
el->intensity=1.6f;
el->fallstart=280.f+rr*20.f;
el->fallend = el->fallstart + 280.f;
el->exist=1;
el->rgb.r = Project.torch.r - rr * 0.1f;
el->rgb.g = Project.torch.g - rr * 0.1f;
el->rgb.b = Project.torch.b - rr * 0.1f;
el->duration=0;
el->extras=0;
}
else if (cur_mr==3)
{
el->pos.x = player.pos.x;
el->pos.y=player.pos.y;
el->pos.z = player.pos.z;
el->intensity=1.8f;
el->fallstart=480.f;
el->fallend = el->fallstart + 480.f;
el->exist=1;
el->rgb.r = 1.f;
el->rgb.g = 0.5f;
el->rgb.b = 0.8f;
el->duration=0;
el->extras=0;
}
else
{
if (flarenum == 0)
el->exist=0;
else
{
float rr=rnd();
long count=0;
for (long i = 0; i < MAX_FLARES; i++)
{
if (flare[i].exist)
{
if (flare[i].flags==0) count++;
}
}
if (count)
{
el->pos.x=player.pos.x;
el->pos.y=player.pos.y;
el->pos.z=player.pos.z;
el->fallstart=140.f+(float)count*0.333333f+rr*5.f;
el->fallend=220.f+(float)count*0.5f+rr*5.f;
el->intensity=1.6f;
el->exist=1;
el->rgb.r=0.01f*count;
el->rgb.g=0.009f*count;
el->rgb.b=0.008f*count;
}
}
}
if (inter.iobj && inter.iobj[0] && inter.iobj[0]->obj
&& (inter.iobj[0]->obj->fastaccess.head_group_origin>-1))
{
el->pos.y=inter.iobj[0]->obj->vertexlist3[inter.iobj[0]->obj->fastaccess.head_group_origin].v.y;
}
}
#define DIV_MAX_FLARELIFE 0.00025f
//-----------------------------------------------------------------------------
void ARX_MAGICAL_FLARES_Draw(LPDIRECT3DDEVICE7 m_pd3dDevice,long FRAMETICKS)
{
/////////FLARE
SETZWRITE(m_pd3dDevice, FALSE );
m_pd3dDevice->SetRenderState( D3DRENDERSTATE_SRCBLEND, D3DBLEND_ONE );
m_pd3dDevice->SetRenderState( D3DRENDERSTATE_DESTBLEND, D3DBLEND_ONE );
SETALPHABLEND(m_pd3dDevice,TRUE);
shinum++;
if (shinum>=10) shinum=1;
long TICKS = lARXTime - FRAMETICKS;
if (TICKS<0)
return;
float zapp,x,y,z,s,r,g,b;
TextureContainer * surf;
BOOL key=!ARX_IMPULSE_Pressed(CONTROLS_CUST_MAGICMODE);
for (long j=1;j<5;j++)
{
switch (j)
{
case 2:
surf=flaretc.lumignon;
break;
case 3:
surf=flaretc.lumignon2;
break;
case 4:
surf=flaretc.plasm;
break;
default:
surf=flaretc.shine[shinum];
break;
}
for (long i=0;iflarecount--;
}
if (ValidDynLight(flare[i].dynlight))
DynLight[flare[i].dynlight].exist=0;
flare[i].dynlight=-1;
flare[i].exist=0;
flarenum--;
}
else
{
z = (flare[i].tolive * DIV_MAX_FLARELIFE);
if ( (flare[i].type==1) )
s=flare[i].size*2*z;
else if (flare[i].type==4)
{
s=flare[i].size*2.f*z+10.f;
}
else s=flare[i].size;
if ( s<3.f )
{
if (flare[i].io)
{
if (ValidIOAddress(flare[i].io))
flare[i].io->flarecount--;
}
if (ValidDynLight(flare[i].dynlight))
DynLight[flare[i].dynlight].exist=0;
flare[i].dynlight=-1;
flare[i].exist=0;
flarenum--;
}
else
{
if (( (s<45) && (flare[i].type==1) ) || (flare[i].type==4) )
{
zapp=((MAX_FLARELIFE-flare[i].tolive)*(MAX_FLARELIFE-flare[i].tolive))*0.000001f;
}
if ((flare[i].type==1) )
{
if (z<0.6f) z=0.6f;
}
g=flare[i].g*z;
r=flare[i].r*z;
b=flare[i].b*z;
zapp = 48 - s * 0.5f;
x=flare[i].x+zapp;
y=flare[i].y+zapp;
flare[i].tv.color=D3DRGB(r,g,b);
flare[i].v.sx=flare[i].tv.sx;
flare[i].v.sy=flare[i].tv.sy;
flare[i].v.sz=flare[i].tv.sz;
DynLight[0].rgb.r=__max(DynLight[0].rgb.r,r);
DynLight[0].rgb.g=__max(DynLight[0].rgb.g,g);
DynLight[0].rgb.b=__max(DynLight[0].rgb.b,b);
if (ValidDynLight(flare[i].dynlight))
{
EERIE_LIGHT * el=&DynLight[flare[i].dynlight];
el->pos.x=flare[i].v.sx;
el->pos.y=flare[i].v.sy;
el->pos.z=flare[i].v.sz;
el->rgb.r=r;
el->rgb.g=g;
el->rgb.b=b;
}
if (!flare[i].io)
{
GDevice->SetRenderState(D3DRENDERSTATE_ZENABLE,FALSE);
}
else
{
GDevice->SetRenderState(D3DRENDERSTATE_ZENABLE,TRUE);
}
if(flare[i].bDrawBitmap)
{
s*=2.f;
EERIEDrawBitmap(m_pd3dDevice,flare[i].v.sx,flare[i].v.sy,s,s,flare[i].v.sz,surf,flare[i].tv.color);
}
else
{
EERIEDrawSprite(m_pd3dDevice,&flare[i].v,(float)s*0.025f+1.f, surf,flare[i].tv.color,2.f);
}
}
}
}
}
}
if (DynLight[0].rgb.r>1.f) DynLight[0].rgb.r=1.f;
if (DynLight[0].rgb.g>1.f) DynLight[0].rgb.g=1.f;
if (DynLight[0].rgb.b>1.f) DynLight[0].rgb.b=1.f;
SETZWRITE(m_pd3dDevice, TRUE );
GDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, TRUE);
}
//-----------------------------------------------------------------------------
void ARX_BOOMS_ClearAllPolyBooms()
{
for(long i=0;iexist=TRUE;
pd->ov.x=poss->x;
pd->ov.y=poss->y;
pd->ov.z=poss->z;
pd->move.x=3.f-6.f*rnd();
pd->move.y=4.f-12.f*rnd();
pd->move.z=3.f-6.f*rnd();
pd->timcreation=tim;
pd->tolive=(unsigned long)(600+rnd()*100);
pd->tc=tc1;
pd->siz=100.f+10.f*rnd();
if (type==1) pd->siz*=2;
pd->zdec=1;
if (type==1)
{
pd->r=0.4f;
pd->g=0.4f;
pd->b=1.f;
}
j=ARX_PARTICLES_GetFree();
if (j!=-1)
{
ParticleCount++;
PARTICLE_DEF * pd=&particle[j];
pd->exist=TRUE;
pd->ov.x=poss->x;
pd->ov.y=poss->y;
pd->ov.z=poss->z;
pd->move.x=3.f-6.f*rnd();
pd->move.y=4.f-12.f*rnd();
pd->move.z=3.f-6.f*rnd();
pd->timcreation=tim;
pd->tolive=(unsigned long)(600+rnd()*100);
pd->tc=tc1;
pd->siz=40.f+30.f*rnd();
if (type==1) pd->siz*=2;
pd->zdec=1;
if (type==1)
{
pd->r=0.4f;
pd->g=0.4f;
pd->b=1.f;
}
}
}
EERIE_3D pos;
Vector_Copy(&pos,poss);
typ=0;
F2L((poss->x*ACTIVEBKG->Xmul),&x0);
F2L((poss->z*ACTIVEBKG->Zmul),&z0);
x1=x0+3;
x0=x0-3;
z1=z0+3;
z0=z0-3;
if (x0<0) x0=0;
else if (x0>=ACTIVEBKG->Xsize) x0=ACTIVEBKG->Xsize-1;
if (x1<0) x1=0;
else if (x1>=ACTIVEBKG->Xsize) x1=ACTIVEBKG->Xsize-1;
if (z0<0) z0=0;
else if (z0>=ACTIVEBKG->Zsize) z0=ACTIVEBKG->Zsize-1;
if (z1<0) z1=0;
else if (z1>=ACTIVEBKG->Zsize) z1=ACTIVEBKG->Zsize-1;
long nbvert;
float temp_u1[4];
float temp_v1[4];
ARX_CHECK_SHORT(z0);
ARX_CHECK_SHORT(x0);
ARX_CHECK_SHORT(z1);
ARX_CHECK_SHORT(x1);
if( !bSoftRender )
{ //We never add BOOMS particle with this flag to prevent any render issues. TO DO check for blending of DrawPrimitve and DrawPrimitiveVB
for (j=z0;j<=z1;j++)
for (i=x0;i<=x1;i++)
{
eg=(EERIE_BKG_INFO *)&ACTIVEBKG->Backg[i+j*ACTIVEBKG->Xsize];
for (long l = 0; l < eg->nbpoly; l++)
{
ep=&eg->polydata[l];
if (ep->type & POLY_QUAD) nbvert=4;
else nbvert=3;
if ((ep->type & POLY_TRANS) && !(ep->type & POLY_WATER)) goto suite;
dod=1;
if ((ddd=Distance3D(ep->v[0].sx,ep->v[0].sy,ep->v[0].sz,poss->x,poss->y,poss->z))v[k].sx,ep->v[k].sy,ep->v[k].sz,poss->x,poss->y,poss->z);
if (ddd>BOOM_RADIUS) dod=0;
else
{
temp_u1[k]=0.5f-((ddd/BOOM_RADIUS)*0.5f);
temp_v1[k]=0.5f-((ddd/BOOM_RADIUS)*0.5f);
}
}
if (dod)
{
n=ARX_BOOMS_GetFree();
if (n>=0)
{
BoomCount++;
POLYBOOM * pb=&polyboom[n];
pb->type=(short)typ;
pb->exist=1;
pb->ep=ep;
pb->tc=tc2;
pb->tolive=10000;
pb->timecreation=tim;
pb->tx=ARX_CLEAN_WARN_CAST_SHORT(i);
pb->tz=ARX_CLEAN_WARN_CAST_SHORT(j);
for (int k=0;ku[k]=temp_u1[k];
pb->v[k]=temp_v1[k];
}
pb->nbvert=(short)nbvert;
}
}
}
suite:
;
}
}
}
}
//-----------------------------------------------------------------------------
void Add3DBoom(EERIE_3D * position, EERIE_3DOBJ *pObj3DSphere)
{
float dist=Distance3D(player.pos.x,player.pos.y-160.f,player.pos.z,position->x,position->y,position->z);
EERIE_3D poss;
Vector_Copy(&poss,position);
ARX_SOUND_PlaySFX(SND_SPELL_FIRE_HIT, &poss);
if (dist<300)
{
float onedist=1.f/dist;
EERIE_3D vect;
vect.x=(player.pos.x-position->x)*onedist;
vect.y=(player.pos.y-160.f-position->y)*onedist;
vect.z=(player.pos.z-position->z)*onedist;
float power=(300.f-dist)*DIV80;
player.physics.forces.x+=vect.x*power;
player.physics.forces.y+=vect.y*power;
player.physics.forces.z+=vect.z*power;
}
for (long i=0;ishow!=1 ) continue;
if ( !(inter.iobj[i]->ioflags & IO_ITEM) ) continue;
if ( inter.iobj[i]->obj)
if ( inter.iobj[i]->obj->pbox)
{
for (long k=0;kobj->pbox->nb_physvert;k++)
{
float dist=EEDistance3D( &inter.iobj[i]->obj->pbox->vert[k].pos, position);
if (dist<300.f)
{
inter.iobj[i]->obj->pbox->active=1;
inter.iobj[i]->obj->pbox->stopcount=0;
float onedist=1.f/dist;
EERIE_3D vect;
vect.x=(inter.iobj[i]->obj->pbox->vert[k].pos.x-position->x)*onedist;
vect.y=(inter.iobj[i]->obj->pbox->vert[k].pos.y-position->y)*onedist;
vect.z=(inter.iobj[i]->obj->pbox->vert[k].pos.z-position->z)*onedist;
float power = (300.f - dist) * 10.f;
inter.iobj[i]->obj->pbox->vert[k].velocity.x+=vect.x*power;
inter.iobj[i]->obj->pbox->vert[k].velocity.y+=vect.y*power;
inter.iobj[i]->obj->pbox->vert[k].velocity.z+=vect.z*power;
}
}
}
}
}
}
//-----------------------------------------------------------------------------
void UpdateObjFx(LPDIRECT3DDEVICE7 pd3dDevice, EERIE_CAMERA * cam)
{
unsigned long framediff;
float val,aa,bb;
float t1,t2,t3;
long p;
EERIE_3D pos;
D3DTLVERTEX v[3];
v[0]= D3DTLVERTEX( D3DVECTOR( 0, 0, 0.001f ), 1.f, D3DRGB(1.f,1.f,1.f), 1, 0.f, 0.f);
v[1]= D3DTLVERTEX( D3DVECTOR( 0, 0, 0.001f ), 1.f, D3DRGB(1.f,1.f,1.f), 1, 1.f, 0.f);
v[2]= D3DTLVERTEX( D3DVECTOR( 0, 0, 0.001f ), 1.f, D3DRGB(1.f,1.f,1.f), 1, 1.f, 1.f);
D3DTLVERTEX v2[3];
v[0]= D3DTLVERTEX( D3DVECTOR( 0, 0, 0.001f ), 1.f, D3DRGB(1.f,1.f,1.f), 1, 0.f, 0.f);
v[1]= D3DTLVERTEX( D3DVECTOR( 0, 0, 0.001f ), 1.f, D3DRGB(1.f,1.f,1.f), 1, 1.f, 0.f);
v[2]= D3DTLVERTEX( D3DVECTOR( 0, 0, 0.001f ), 1.f, D3DRGB(1.f,1.f,1.f), 1, 1.f, 1.f);
pd3dDevice->SetRenderState( D3DRENDERSTATE_SRCBLEND, D3DBLEND_ONE );
pd3dDevice->SetRenderState( D3DRENDERSTATE_DESTBLEND, D3DBLEND_ONE );
SETALPHABLEND(pd3dDevice,TRUE);
SETZWRITE(pd3dDevice, FALSE );
for (long i=0;iobjfx[i].duration)
{
objfx[i].exist=FALSE;
if (ValidDynLight(objfx[i].dynlight))
DynLight[objfx[i].dynlight].exist=0;
objfx[i].dynlight=-1;
continue;
}
val=(float)framediff/(float)objfx[i].duration;
pos.x=objfx[i].pos.x+objfx[i].move.x*val;
pos.y=objfx[i].pos.y+objfx[i].move.y*val;
pos.z=objfx[i].pos.z+objfx[i].move.z*val;
EERIE_3D angle;
EERIE_3D scale;
EERIE_RGB color;
scale.x=1.f+objfx[i].scale.x*val;
scale.y=1.f+objfx[i].scale.y*val;
scale.z=1.f+objfx[i].scale.z*val;
if (Project.improve)
{
color.r=1.f-objfx[i].fade.r*val;
color.g=0.f;
color.b=1.f-objfx[i].fade.b*val;
}
else
{
color.r=1.f-objfx[i].fade.r*val;
color.g=1.f-objfx[i].fade.g*val;
color.b=1.f-objfx[i].fade.b*val;
}
angle.a=0.f;
angle.b=0.f;
angle.g=0.f;
DrawEERIEObjEx(pd3dDevice,objfx[i].obj,
&angle,&pos,&scale,&color);
if (objfx[i].dynlight!=-1)
{
DynLight[objfx[i].dynlight].fallend=250.f+450.f*val;
DynLight[objfx[i].dynlight].fallstart=150.f+50.f*val;
DynLight[objfx[i].dynlight].rgb.r=1.f-val;
DynLight[objfx[i].dynlight].rgb.g=0.9f-val*0.9f;
DynLight[objfx[i].dynlight].rgb.b=0.5f-val*0.5f;
DynLight[objfx[i].dynlight].pos.x=pos.x;
DynLight[objfx[i].dynlight].pos.y=pos.y;
DynLight[objfx[i].dynlight].pos.z=pos.z;
}
if (objfx[i].special & SPECIAL_RAYZ)
{
SETCULL(pd3dDevice,D3DCULL_NONE);
for (long k=0;k<8;k++)
{
aa=objfx[i].spe[k].g;
bb=objfx[i].speinc[k].g;
if (ARXPausedTimer)
{
}
else
{
objfx[i].spe[k].a+=objfx[i].speinc[k].a;
objfx[i].spe[k].b+=objfx[i].speinc[k].b;
}
for (p=0;p<3;p++)
{
v[p].sx=pos.x;
v[p].sy=pos.y;
v[p].sz=pos.z;
}
t1=100.f*scale.x;
t2=100.f*scale.y;
t3=100.f*scale.z;
v[1].sx-=EEsin(DEG2RAD(objfx[i].spe[k].b))*t1;
v[1].sy+=EEsin(DEG2RAD(objfx[i].spe[k].a))*t2;
v[1].sz+=EEcos(DEG2RAD(objfx[i].spe[k].b))*t3;
v[2].sx=v[0].sx-EEsin(DEG2RAD(MAKEANGLE(objfx[i].spe[k].b+bb)))*t1;
v[2].sy=v[0].sy+EEsin(DEG2RAD(MAKEANGLE(objfx[i].spe[k].a+aa)))*t2;
v[2].sz=v[0].sz+EEcos(DEG2RAD(MAKEANGLE(objfx[i].spe[k].b+bb)))*t3;
EE_RTP(&v[0],&v2[0]);
EE_RTP(&v[1],&v2[1]);
EE_RTP(&v[2],&v2[2]);
if (Project.improve)
{
for (p=0;p<3;p++)
v2[p].color=D3DRGB(color.r/(3.f+(float)p),0.f,color.b/(5.f+(float)p));
}
else
{
for (p=0;p<3;p++)
v2[p].color=D3DRGB(color.r/(3.f+(float)p),color.g/(4.f+(float)p),color.b/(5.f+(float)p));
}
SETTC(pd3dDevice,NULL);
EERIEDRAWPRIM(pd3dDevice,D3DPT_TRIANGLEFAN, D3DFVF_TLVERTEX| D3DFVF_DIFFUSE , v2, 3, 0, bSoftRender?EERIE_USEVB:0 );
}
}
}
}
}
//-----------------------------------------------------------------------------
void ARX_PARTICLES_FirstInit()
{
smokeparticle=MakeTCFromFile("Graph\\Particles\\smoke.bmp");
bloodsplat[0]=bloodsplatter=MakeTCFromFile("Graph\\Particles\\new_blood.bmp");
bloodsplat[1]=MakeTCFromFile("Graph\\Particles\\new_blood_splat1.bmp");
bloodsplat[2]=MakeTCFromFile("Graph\\Particles\\new_blood_splat2.bmp");
bloodsplat[3]=MakeTCFromFile("Graph\\Particles\\new_blood_splat3.bmp");
bloodsplat[4]=MakeTCFromFile("Graph\\Particles\\new_blood_splat4.bmp");
bloodsplat[5]=MakeTCFromFile("Graph\\Particles\\new_blood_splat5.bmp");
water_splat[0]=MakeTCFromFile("Graph\\Particles\\[fx]_Water01.bmp");
water_splat[1]=MakeTCFromFile("Graph\\Particles\\[fx]_Water02.bmp");
water_splat[2]=MakeTCFromFile("Graph\\Particles\\[fx]_Water03.bmp");
water_drop[0]=MakeTCFromFile("Graph\\Particles\\[fx]_Water_drop01.bmp");
water_drop[1]=MakeTCFromFile("Graph\\Particles\\[fx]_Water_drop02.bmp");
water_drop[2]=MakeTCFromFile("Graph\\Particles\\[fx]_Water_drop03.bmp");
healing=MakeTCFromFile("Graph\\Particles\\heal_0005.bmp");
tzupouf=MakeTCFromFile("Graph\\Obj3D\\Textures\\(FX)_tsu_greypouf.bmp");
fire2=MakeTCFromFile("Graph\\Particles\\fire2.bmp");
}
//-----------------------------------------------------------------------------
void ARX_PARTICLES_ClearAll()
{
memset(particle,0,sizeof(PARTICLE_DEF)*MAX_PARTICLES);
ParticleCount=0;
}
//-----------------------------------------------------------------------------
long ARX_PARTICLES_GetFree()
{
for ( long i = 0 ; i < MAX_PARTICLES ; i++)
if ( !particle[i].exist )
{
PARTICLE_DEF *pd = &particle[i];
pd->type = 0;
pd->r = 1.f;
pd->g = 1.f;
pd->b = 1.f;
pd->tc = NULL;
pd->special = 0;
pd->source = NULL;
pd->delay = 0;
return i;
}
return -1;
}
//-----------------------------------------------------------------------------
void MagFX(float posx,float posy,float posz)
{
long j;
j=ARX_PARTICLES_GetFree();
if ((j!=-1) && (!ARXPausedTimer))
{
ParticleCount++;
PARTICLE_DEF * pd = &particle[j];
pd->exist = TRUE;
pd->zdec = 0;
pd->ov.x = posx+rnd()*6.f-rnd()*12.f;
pd->ov.y = posy+rnd()*6.f-rnd()*12.f;
pd->ov.z = posz;
pd->move.x = 6.f-rnd()*12.f;
pd->move.y = -8.f+rnd()*16.f;
pd->move.z = 0.f;
pd->scale.x = 4.4f;
pd->scale.y = 4.4f;
pd->scale.z = 1.f;
pd->timcreation = lARXTime;
pd->tolive = 1500+(unsigned long)(rnd()*900.f);
pd->tc = healing;
pd->r = 1.f;
pd->g = 0.f;
pd->b = 1.f;
pd->siz = 56.f;
pd->type = PARTICLE_2D;
}
}
//-----------------------------------------------------------------------------
void MakeBookFX(float posx,float posy,float posz)
{
long j;
for (long i=0;i<12;i++)
{
j=ARX_PARTICLES_GetFree();
if ((j!=-1) && (!ARXPausedTimer))
{
ParticleCount++;
PARTICLE_DEF * pd=&particle[j];
pd->exist = TRUE;
pd->zdec = 0;
pd->ov.x = posx+rnd()*6.f-rnd()*12.f;
pd->ov.y = posy+rnd()*6.f-rnd()*12.f;
pd->ov.z = posz;
pd->move.x = 6.f-rnd()*12.f;
pd->move.y = -8.f+rnd()*16.f;
pd->move.z = 0.f;
pd->scale.x = 4.4f;
pd->scale.y = 4.4f;
pd->scale.z = 1.f;
pd->timcreation = lARXTime;
pd->tolive = 1500+(unsigned long)(rnd()*900.f);
pd->tc = healing;
pd->r = 1.f;
pd->g = 0.f;
pd->b = 1.f;
pd->siz = 56.f;
pd->type = PARTICLE_2D;
}
}
for (int i=0;i<5;i++)
{
j=ARX_PARTICLES_GetFree();
if ((j!=-1) && (!ARXPausedTimer))
{
ParticleCount++;
PARTICLE_DEF * pd=&particle[j];
pd->exist = TRUE;
pd->zdec = 0;
pd->ov.x = posx - i * 2;
pd->ov.y = posy - i * 2;
pd->ov.z = posz;
pd->move.x = -(float)(i)*DIV2;
pd->move.y = -(float)(i)*DIV2;
pd->move.z = 0.f;
pd->scale.y = pd->scale.x = (float)(i*10);
pd->scale.z = 0.f;
pd->timcreation = lARXTime;
pd->tolive = 1200+(unsigned long)(rnd()*400.f);
pd->tc = ITC.book;
pd->r = 1.f-(float)i*0.1f;
pd->g = (float)i*0.1f;
pd->b = 0.5f-(float)i*0.1f;
pd->siz = 32.f+i*4;
pd->type = PARTICLE_2D;
}
}
NewSpell=1;
}
//-----------------------------------------------------------------------------
int ARX_GenereOneEtincelle(EERIE_3D *pos,EERIE_3D *dir)
{
int i;
i=ARX_PARTICLES_GetFree();
if(i<0) return -1;
ParticleCount++;
PARTICLE_DEF * pd=&particle[i];
pd->exist = TRUE;
pd->type = PARTICLE_ETINCELLE;
pd->special = GRAVITY;
pd->ov = pd->oldpos = *pos;
pd->move = *dir;
pd->tolive = 1000+(int)(rnd()*500.f);
pd->timcreation = lARXTime;
pd->r = ET_R;
pd->g = ET_G;
pd->b = ET_B;
pd->tc = GTC;
pd->mask = ET_MASK;
return i;
}
//-----------------------------------------------------------------------------
void ARX_GenereSpheriqueEtincelles(EERIE_3D *pos,float r,TextureContainer *tc,float rr,float g,float b,int mask)
{
GTC=tc;
ET_R=rr;
ET_G=g;
ET_B=b;
ET_MASK=mask;
int nb=rand()&0x1F;
while(nb)
{
EERIE_3D dir;
float a = DEG2RAD(rnd()*360.f);
float b = DEG2RAD(rnd()*360.f);
dir.x=(float) r*EEsin(a)*EEcos(b);
dir.z=(float) r*EEsin(a)*EEsin(b);
dir.y=(float) r*EEcos(a);
ARX_GenereOneEtincelle(pos,&dir);
nb--;
}
}
//-----------------------------------------------------------------------------
// flags & 1 = spawn_body_chunk
void ARX_PARTICLES_Spawn_Splat(EERIE_3D * pos,float dmgs,D3DCOLOR col,long vert,INTERACTIVE_OBJ * io,long flags)
{
float power;
power=(dmgs*DIV60)+0.9f;
float r,g,b;
r=(float)((long)((col>>16) & 255))*DIV255;
g=(float)((long)((col>>8) & 255))*DIV255;
b=(float)((long)((col) & 255))*DIV255;
for (long kk=0;kk<20;kk++)
{
long j=ARX_PARTICLES_GetFree();
if (j!=-1)
{
ParticleCount++;
PARTICLE_DEF * pd=&particle[j];
pd->special = PARTICLE_SUB2 | SUBSTRACT | GRAVITY;
pd->exist = TRUE;
pd->ov.x = pos->x;
pd->ov.y = pos->y;
pd->ov.z = pos->z;
pd->move.x = (rnd()*10-5.f)*2.3f;
pd->move.y = (rnd()*10-5.f)*2.3f;
pd->move.z = (rnd()*10-5.f)*2.3f;
pd->timcreation = lARXTime;
pd->tolive = (unsigned long)(1000+dmgs*3);
pd->tc = blood_splat;
pd->siz = (float)0.3f+0.01f*power;
pd->scale.x = 0.2f+(float)0.3f*power;
pd->scale.y = 0.2f+(float)0.3f*power;
pd->scale.z = 0.2f+(float)0.3f*power;
pd->zdec = 1;
pd->b = b;
pd->g = g;
pd->r = r;
}
}
}
//-----------------------------------------------------------------------------
void ARX_PARTICLES_SpawnWaterSplash(EERIE_3D *_ePos)
{
for (long kk=0;kkspecial = FADE_IN_AND_OUT | ROTATING | MODULATE_ROTATION | DISSIPATING | GRAVITY;
pd->special |= SPLAT_WATER;
pd->exist = TRUE;
pd->ov.x = _ePos->x + rnd()*30;
pd->ov.y = _ePos->y - rnd()*20;
pd->ov.z = _ePos->z + rnd()*30;
pd->move.x = (frand2()*5)*1.3f;
pd->move.y = -(rnd()*5)*2.3f;
pd->move.z = (frand2()*5)*1.3f;
pd->timcreation = lARXTime;
pd->tolive = (unsigned long)(1000+rnd()*300);
float fRandom = rnd()*2;
ARX_CHECK_INT(fRandom);
int t = ARX_CLEAN_WARN_CAST_INT(fRandom);
pd->tc=water_drop[t];
pd->siz = 0.4f;
float s = rnd();
pd->scale.x = 1;
pd->scale.y = 1;
pd->scale.z = 1;
pd->zdec=1;
pd->b = s;
pd->g = s;
pd->r = s;
}
}
}
//-----------------------------------------------------------------------------
void SpawnFireballTail(EERIE_3D * poss,EERIE_3D * vecto,float level,long flags)
{
if (explo[0]==NULL) return;
level*=2.f;
for (long nn=0;nn<2;nn++)
{
long j=ARX_PARTICLES_GetFree();
if (j!=-1)
{
ParticleCount++;
PARTICLE_DEF * pd=&particle[j];
pd->special = FIRE_TO_SMOKE | FADE_IN_AND_OUT | PARTICLE_ANIMATED | ROTATING | MODULATE_ROTATION;
pd->fparam = 0.02f-rnd()*0.02f;
pd->exist = TRUE;
pd->ov.x = poss->x;
pd->ov.y = poss->y;
pd->ov.z = poss->z;
pd->move.x = 0;
pd->move.y = -rnd() * 3.f;
pd->move.z = 0;
pd->timcreation = lARXTime;
pd->tc = explo[0];
pd->r = 0.7f;
pd->g = 0.7f;
pd->b = 0.7f;
pd->siz = level+2.f*rnd();
if (flags & 1)
{
pd->tolive = (unsigned long)(400+rnd()*100);
pd->siz *= 0.7f;
pd->scale.z=pd->scale.y=pd->scale.x=level*0.7f;
}
else
{
pd->scale.x=level;
pd->scale.y=level;
pd->scale.z=level;
pd->tolive=(unsigned long)(800+rnd()*100);
}
pd->cval1=0;
pd->cval2=MAX_EXPLO-1;
if (nn==1)
{
pd->delay=(unsigned long)(float)(150+rnd()*100.f);
pd->ov.x=poss->x+vecto->x*pd->delay;
pd->ov.y=poss->y+vecto->y*pd->delay;
pd->ov.z=poss->z+vecto->z*pd->delay;
}
}
}
}
//-----------------------------------------------------------------------------
void LaunchFireballBoom(EERIE_3D * poss,float level,EERIE_3D * direction,EERIE_RGB * rgb)
{
level*=1.6f;
if (explo[0]==NULL) return;
for (long nn=0;nn<1;nn++)
{
long j=ARX_PARTICLES_GetFree();
if (j!=-1)
{
ParticleCount++;
PARTICLE_DEF * pd=&particle[j];
pd->special=FIRE_TO_SMOKE | FADE_IN_AND_OUT | PARTICLE_ANIMATED;
pd->exist=TRUE;
pd->ov.x=poss->x;
pd->ov.y=poss->y;
pd->ov.z=poss->z;
if (direction)
Vector_Copy(&pd->move,direction);
else
{
pd->move.x = 0.f;
pd->move.y = -rnd() * 5.f;
pd->move.z = 0.f;
}
pd->timcreation = lARXTime;
pd->tolive = (unsigned long)(1600+rnd()*600);
pd->tc = explo[0];
pd->siz = level*3.f+2.f*rnd();
pd->scale.x = level*3.f;
pd->scale.y = level*3.f;
pd->scale.z = level*3.f;
pd->zdec = 1;
pd->cval1 = 0;
pd->cval2 = MAX_EXPLO-1;
if (rgb)
{
pd->r=rgb->r;
pd->g=rgb->g;
pd->b=rgb->b;
}
if (nn==1)
{
pd->delay=300;
pd->tolive/=2;
pd->scale.x*=2;
pd->scale.y*=2;
pd->scale.z*=2;
}
}
}
}
//-----------------------------------------------------------------------------
void ARX_PARTICLES_Render(LPDIRECT3DDEVICE7 pd3dDevice,EERIE_CAMERA * cam)
{
if (!ACTIVEBKG) return;
TreatBackgroundActions();
if (ParticleCount==0) return;
register long i;
register long xx,yy;
register unsigned long tim;
long framediff;
long framediff2;
long t;
register D3DTLVERTEX in,inn,out;
register D3DCOLOR color;
register float siz,siz2,r;
register float val;
register float fd;
register float rott;
tim = ARXTimeUL();//treat warning C4244 conversion from 'float' to 'unsigned long'
SETCULL(pd3dDevice,D3DCULL_NONE);
GDevice->SetRenderState(D3DRENDERSTATE_FOGCOLOR,0);
TextureContainer * tc=NULL;
long pcc=ParticleCount;
for (i=0;iexist)
{
framediff=part->timcreation+part->tolive-tim;
framediff2=tim-part->timcreation;
if (framediff2 < (long)part->delay) continue;
if (part->delay>0)
{
part->timcreation+=part->delay;
part->delay=0;
if ((part->special & DELAY_FOLLOW_SOURCE) && (part->sourceionum>=0) && (inter.iobj[part->sourceionum]))
{
part->ov.x = part->source->x;
part->ov.y = part->source->y;
part->ov.z = part->source->z;
INTERACTIVE_OBJ * target=inter.iobj[part->sourceionum];
EERIE_3D vector;
vector.x=part->ov.x-target->pos.x;
vector.y=(part->ov.y-target->pos.y)*DIV2;
vector.z=part->ov.z-target->pos.z;
float t=1.f/TRUEVector_Magnitude(&vector);
vector.x*=t;
vector.y*=t;
vector.z*=t;
part->move.x = vector.x * 18 + rnd() - 0.5f;
part->move.y = vector.y * 5 + rnd() - 0.5f;
part->move.z = vector.z * 18 + rnd() - 0.5f;
}
continue;
}
if (!(part->type & PARTICLE_2D))
{
F2L((part->ov.x*ACTIVEBKG->Xmul),&xx);
F2L((part->ov.z*ACTIVEBKG->Zmul),&yy);
if ((xx<0) || (yy<0) || (xx>ACTIVEBKG->Xsize) || (yy>ACTIVEBKG->Zsize))
{
part->exist=FALSE;
ParticleCount--;
continue;
}
FAST_BKG_DATA * feg=(FAST_BKG_DATA *)&ACTIVEBKG->fastdata[xx][yy];
if (!feg->treat)
{
part->exist=FALSE;
ParticleCount--;
continue;
}
}
if (framediff<=0)
{
if ((part->special & FIRE_TO_SMOKE) && (rnd()>0.7f))
{
part->ov.x+=part->move.x;
part->ov.y+=part->move.y;
part->ov.z+=part->move.z;
part->tolive += (part->tolive >> 2) + (part->tolive >> 3);
part->special&=~FIRE_TO_SMOKE;
part->timcreation=tim;
part->tc = smokeparticle;
part->scale.x*=2.4f;
part->scale.y*=2.4f;
part->scale.z*=2.4f;
if (part->scale.x<0.f) part->scale.x*=-1.f;
if (part->scale.y<0.f) part->scale.y*=-1.f;
if (part->scale.z<0.f) part->scale.z*=-1.f;
part->r=0.45f;
part->g=0.45f;
part->b=0.45f;
part->move.x*=DIV2;
part->move.y*=DIV2;
part->move.z*=DIV2;
part->siz*=DIV3;
part->special&=~FIRE_TO_SMOKE;
part->timcreation=tim;
part->tc = smokeparticle;
framediff=part->timcreation+part->tolive-tim;
}
else
{
part->exist=FALSE;
ParticleCount--;
continue;
}
}
if((part->special & FIRE_TO_SMOKE2)&&(framediff2>(long)(part->tolive-(part->tolive>>2))))
{
part->special&=~FIRE_TO_SMOKE2;
int j=ARX_PARTICLES_GetFree();
if(j>=0)
{
ParticleCount++;
PARTICLE_DEF * pd=&particle[j];
particle[j]=particle[i];
pd->exist=1;
pd->zdec=0;
pd->special|=SUBSTRACT;
pd->ov.x=part->oldpos.x;
pd->ov.y=part->oldpos.y;
pd->ov.z=part->oldpos.z;
pd->timcreation=tim;
pd->tc = tzupouf;
pd->scale.x*=4.f;
pd->scale.y*=4.f;
pd->scale.z*=4.f;
if (pd->scale.x<0.f) pd->scale.x*=-1.f;
if (pd->scale.y<0.f) pd->scale.y*=-1.f;
if (pd->scale.z<0.f) pd->scale.z*=-1.f;
pd->r = 1.f;
pd->g = 1.f;
pd->b = 1.f;
pd->move.x*=DIV2;
pd->move.y*=DIV2;
pd->move.z*=DIV2;
pd->siz*=DIV3;
}
}
val=(part->tolive-framediff)*DIV100;
if ((part->special & FOLLOW_SOURCE) && (part->sourceionum>=0) && (inter.iobj[part->sourceionum]))
{
inn.sx=in.sx=part->source->x;
inn.sy=in.sy=part->source->y;
inn.sz=in.sz=part->source->z;
}
else if ((part->special & FOLLOW_SOURCE2) && (part->sourceionum>=0) && (inter.iobj[part->sourceionum]))
{
inn.sx=in.sx=part->source->x+part->move.x*val;
inn.sy=in.sy=part->source->y+part->move.y*val;
inn.sz=in.sz=part->source->z+part->move.z*val;
}
else
{
inn.sx=in.sx=part->ov.x+part->move.x*val;
inn.sy=in.sy=part->ov.y+part->move.y*val;
inn.sz=in.sz=part->ov.z+part->move.z*val;
}
if (part->special & GRAVITY)
{
inn.sy += 0.98f * 1.5f * val * val;
in.sy=inn.sy;
}
if (part->special & PARTICLE_NOZBUFFER)
{
GDevice->SetRenderState(D3DRENDERSTATE_ZENABLE,FALSE);
}
else
{
GDevice->SetRenderState(D3DRENDERSTATE_ZENABLE,TRUE);
}
if (part->special & FADE_IN_AND_OUT)
{
t=part->tolive>>1;
if (framediff2<=t)
{
r=((float)framediff2/(float)t);
}
else
{
fd=((float)(framediff2-t)/(float)t);
r=1.f-fd;
}
fd=((float)framediff2/(float)part->tolive);
}
else
{
fd=((float)framediff2/(float)part->tolive);
r=1.f-fd;
}
if (!(part->type & PARTICLE_2D))
{
EERIE_SPHERE sp;
sp.origin.x=in.sx;
sp.origin.y=in.sy;
sp.origin.z=in.sz;
EERIETreatPoint(&inn,&out);
if (out.rhw<0) continue;
if (out.sz>cam->cdepth*fZFogEnd) continue;
if (part->special & PARTICLE_SPARK)
{
if (part->special & NO_TRANS)
{
SETALPHABLEND(pd3dDevice,FALSE);
}
else
{
SETALPHABLEND(pd3dDevice,TRUE);
if (part->special & SUBSTRACT)
{
pd3dDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_ZERO);
pd3dDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCCOLOR);
}
else
{
pd3dDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_ONE);
pd3dDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_ONE);
}
}
SETCULL(pd3dDevice,D3DCULL_NONE);
EERIE_3D vect;
vect.x=part->oldpos.x-in.sx;
vect.y=part->oldpos.y-in.sy;
vect.z=part->oldpos.z-in.sz;
Vector_Normalize(&vect);
D3DTLVERTEX tv[3];
tv[0].color=D3DRGB(part->r,part->g,part->b);
tv[1].color=0xFF666666;
tv[2].color = 0xFF000000;
tv[0].sx=out.sx;
tv[0].sy=out.sy;
tv[0].sz=out.sz;
tv[0].rhw=out.rhw;
D3DTLVERTEX temp;
temp.sx=in.sx+rnd()*0.5f;
temp.sy=in.sy+0.8f;
temp.sz=in.sz+rnd()*0.5f;
EERIETreatPoint(&temp,&tv[1]);
temp.sx=in.sx+vect.x*part->fparam;
temp.sy=in.sy+vect.y*part->fparam;
temp.sz=in.sz+vect.z*part->fparam;
EERIETreatPoint(&temp,&tv[2]);
SETTC(pd3dDevice,NULL);
ComputeFogVertex(tv);
EERIEDRAWPRIM(pd3dDevice,D3DPT_TRIANGLESTRIP, D3DFVF_TLVERTEX| D3DFVF_DIFFUSE , tv, 3, 0, bSoftRender?EERIE_USEVB:0 );
if(!ARXPausedTimer)
{
part->oldpos.x=in.sx;
part->oldpos.y=in.sy;
part->oldpos.z=in.sz;
}
continue;
}
if (part->special & SPLAT_GROUND)
{
siz=part->siz+part->scale.x*fd;
sp.radius=siz*10;
if (CheckAnythingInSphere(&sp,0,1))
{
EERIE_RGB rgb;
rgb.r=part->r;
rgb.g=part->g;
rgb.b=part->b;
if (rnd()<0.9f)
SpawnGroundSplat(&sp,&rgb,sp.radius,0);
part->exist=FALSE;
ParticleCount--;
continue;
}
}
if (part->special & SPLAT_WATER)
{
siz=part->siz+part->scale.x*fd;
sp.radius=siz*(10 + rnd()*20);
if (CheckAnythingInSphere(&sp,0,1))
{
EERIE_RGB rgb;
rgb.r=part->r*0.5f;
rgb.g=part->g*0.5f;
rgb.b=part->b*0.5f;
if (rnd()<0.9f)
SpawnGroundSplat(&sp,&rgb,sp.radius,2);
part->exist=FALSE;
ParticleCount--;
continue;
}
}
}
if ((part->special & DISSIPATING) && (out.sz<0.05f))
{
out.sz=(out.sz)*20.f;
r*=out.sz;
}
if (r>0.f)
{
if (part->special & NO_TRANS)
{
SETALPHABLEND(pd3dDevice,FALSE);
}
else
{
SETALPHABLEND(pd3dDevice,TRUE);
if (part->special & SUBSTRACT)
{
pd3dDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_ZERO);
pd3dDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCCOLOR);
}
else
{
pd3dDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_ONE);
pd3dDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_ONE);
}
}
EERIE_3D op=part->oldpos;
if(!ARXPausedTimer)
{
part->oldpos.x=in.sx;
part->oldpos.y=in.sy;
part->oldpos.z=in.sz;
}
if (part->special & PARTICLE_GOLDRAIN)
{
float v=(rnd()-0.5f)*DIV5;
if ( (part->r+v<=1.f) && (part->r+v>0.f)
&& (part->g+v<=1.f) && (part->g+v>0.f)
&& (part->b+v<=1.f) && (part->b+v>0.f) )
{
part->r+=v;
part->g+=v;
part->b+=v;
}
}
if (Project.improve)
{
color=D3DRGB(part->r*r,0.f,part->b*r);
}
else color=D3DRGB(part->r*r,part->g*r,part->b*r);
tc=part->tc;
if ((tc==explo[0]) && (part->special & PARTICLE_ANIMATED))
{
long animrange=part->cval2-part->cval1;
float tt=(float)framediff2/(float)part->tolive*animrange;
long num;
F2L(tt,&num);
if (numcval1) num=part->cval1;
if (num>part->cval2) num=part->cval2;
tc=explo[num];
}
siz=part->siz+part->scale.x*fd;
if (part->special & ROTATING)
{
if (part->special & MODULATE_ROTATION) rott=MAKEANGLE((float)(tim+framediff2)*part->fparam);
else rott=(MAKEANGLE((float)(tim+framediff2*2)*DIV4));
if (part->type & PARTICLE_2D)
{}
else
{
float temp;
if (part->zdec) temp=0.0001f;
else temp=2.f;
if (part->special & PARTICLE_SUB2)
{
D3DTLVERTEX in2;
memcpy(&in2,&in,sizeof(D3DTLVERTEX));
pd3dDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_ONE);
pd3dDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_ONE);
EERIEDrawRotatedSprite(pd3dDevice,&in,siz,tc,color,temp,rott);
pd3dDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_ZERO);
pd3dDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCCOLOR);
EERIEDrawRotatedSprite(pd3dDevice,&in2,siz,tc,0xFFFFFFFF,temp,rott);
}
else
EERIEDrawRotatedSprite(pd3dDevice,&in,siz,tc,color,temp,rott);
}
}
else if (part->type & PARTICLE_2D)
{
siz2=part->siz+part->scale.y*fd;
if (part->special & PARTICLE_SUB2)
{
D3DTLVERTEX in2;
memcpy(&in2,&in,sizeof(D3DTLVERTEX));
pd3dDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_ONE);
pd3dDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_ONE);
EERIEDrawBitmap(pd3dDevice,in.sx,in.sy,siz,siz2,in.sz,tc,color);
pd3dDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_ZERO);
pd3dDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCCOLOR);
EERIEDrawBitmap(pd3dDevice,in2.sx,in.sy,siz,siz2,in.sz,tc,0xFFFFFFFF);
}
else
EERIEDrawBitmap(pd3dDevice,in.sx,in.sy,siz,siz2,in.sz,tc,color);
}
else
{
if(part->type & PARTICLE_ETINCELLE)
{
EERIE_3D pos,end;
pos.x=in.sx;
pos.y=in.sy;
pos.z=in.sz;
int color1=RGBA_MAKE((int)(part->r*255.f*r),(int)(part->g*255.f*r),(int)(part->b*255.f*r),255);
end.x=pos.x-(pos.x-op.x)*2.5f;
end.y=pos.y-(pos.y-op.y)*2.5f;
end.z=pos.z-(pos.z-op.z)*2.5f;
Draw3DLineTex2(pd3dDevice,end,pos,2.f,color1 & part->mask,color1);
EERIEDrawSprite(pd3dDevice,&in,.7f,tc,color1,2.f);
}
else
{
float temp;
if (part->zdec) temp=0.0001f;
else temp=2.f;
if (part->special & PARTICLE_SUB2)
{
D3DTLVERTEX in2;
memcpy(&in2,&in,sizeof(D3DTLVERTEX));
pd3dDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_ONE);
pd3dDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_ONE);
EERIEDrawSprite(pd3dDevice,&in,siz,tc,color,temp);
pd3dDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_ZERO);
pd3dDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCCOLOR);
EERIEDrawSprite(pd3dDevice,&in2,siz,tc,0xFFFFFFFF,temp);
}
else
EERIEDrawSprite(pd3dDevice,&in,siz,tc,color,temp);
}
}
}
pcc--;
if (pcc<=0)
{
GDevice->SetRenderState(D3DRENDERSTATE_FOGCOLOR,ulBKGColor);
return;
}
}
}
GDevice->SetRenderState(D3DRENDERSTATE_FOGCOLOR,ulBKGColor);
GDevice->SetRenderState(D3DRENDERSTATE_ZENABLE,TRUE);
}
//-----------------------------------------------------------------------------
void RestoreAllLightsInitialStatus()
{
for (long i=0;istatus=1;
if (GLight[i]->extras & EXTRAS_STARTEXTINGUISHED) GLight[i]->status=0;
if (GLight[i]->status==0)
{
if (ValidDynLight(GLight[i]->tl))
{
DynLight[GLight[i]->tl].exist=0;
}
GLight[i]->tl=-1;
}
}
}
}
extern long FRAME_COUNT;
//-----------------------------------------------------------------------------
// Draws Flame Particles
//-----------------------------------------------------------------------------
void TreatBackgroundActions()
{
if (FRAME_COUNT>0) return;
long n,j;
float sx,sy,sz;
float fZFar=ACTIVECAM->cdepth*fZFogEnd*1.3f;
for (long i=0;ipos, &ACTIVECAM->pos);
if ( dist>fZFar ) // Out of Treat Range
{
ARX_SOUND_Stop(gl->sample);
gl->sample = ARX_SOUND_INVALID_RESOURCE;
continue;
}
if ((gl->extras & EXTRAS_SPAWNFIRE) && (gl->status))
{
long id=ARX_DAMAGES_GetFree();
if (id!=-1)
{
damages[id].radius = gl->ex_radius;
damages[id].damages = gl->ex_radius * DIV7;
damages[id].area=DAMAGE_FULL;
damages[id].duration=1;
damages[id].source=-5;
damages[id].flags = 0;
damages[id].type=DAMAGE_TYPE_MAGICAL | DAMAGE_TYPE_FIRE | DAMAGE_TYPE_NO_FIX;
damages[id].exist=TRUE;
damages[id].pos.x=gl->pos.x;
damages[id].pos.y=gl->pos.y;
damages[id].pos.z=gl->pos.z;
}
}
if (( (gl->extras & EXTRAS_SPAWNFIRE)
|| (gl->extras & EXTRAS_SPAWNSMOKE))
&& (gl->status))
{
if (gl->sample == ARX_SOUND_INVALID_RESOURCE)
{
gl->sample = SND_FIREPLACE;
ARX_SOUND_PlaySFX(gl->sample, &gl->pos, 0.95F + 0.1F * rnd(), ARX_SOUND_PLAY_LOOPED);
}
else
{
ARX_SOUND_RefreshPosition(gl->sample, &gl->pos);
}
long count;
if (distcdepth*DIV8) count=4;
else if (distcdepth*DIV6) count=4;
else if (dist>ACTIVECAM->cdepth*DIV3) count=3;
else count=2;
for (n=0;nex_frequency)))
{
ParticleCount++;
PARTICLE_DEF * pd=&particle[j];
pd->exist=TRUE;
pd->zdec=0;
sy=rnd()*3.14159f;
sx=EEsin(sy);
sz=EEcos(sy);
sy=EEsin(sy);
pd->ov.x=gl->pos.x+gl->ex_radius*sx*rnd();
pd->ov.y=gl->pos.y+gl->ex_radius*sy*rnd();
pd->ov.z=gl->pos.z+gl->ex_radius*sz*rnd();
pd->move.x=(2.f-4.f*rnd())*gl->ex_speed;
pd->move.y=(2.f-22.f*rnd())*gl->ex_speed;
pd->move.z=(2.f-4.f*rnd())*gl->ex_speed;
pd->siz=7.f*gl->ex_size;
pd->tolive=500+(unsigned long)(rnd()*1000.f*gl->ex_speed);
if ((gl->extras & EXTRAS_SPAWNFIRE) && (gl->extras & EXTRAS_SPAWNSMOKE))
pd->special=FIRE_TO_SMOKE;
else pd->special=0;
if (gl->extras & EXTRAS_SPAWNFIRE)
pd->tc = fire2;
else
pd->tc = smokeparticle;
pd->special |= ROTATING | MODULATE_ROTATION;
pd->fparam = 0.1f-rnd()*0.2f*gl->ex_speed;
pd->scale.x = -8.f;
pd->scale.y = -8.f;
pd->scale.z = -8.f;
pd->timcreation = lARXTime;
if (gl->extras & EXTRAS_COLORLEGACY)
{
pd->r=gl->rgb.r;
pd->g=gl->rgb.g;
pd->b=gl->rgb.b;
}
else pd->r=pd->g=pd->b=1.f;
}
if ((gl->extras & EXTRAS_SPAWNFIRE) && (rnd()>0.95f))
{
j=ARX_PARTICLES_GetFree();
if ((j!=-1) && (!ARXPausedTimer) && ((rnd()ex_frequency)))
{
ParticleCount++;
PARTICLE_DEF * pd=&particle[j];
pd->exist=TRUE;
pd->zdec=0;
sy = rnd() * 3.14159f * 2.f - 3.14159f;
sx=EEsin(sy);
sz=EEcos(sy);
sy=EEsin(sy);
pd->ov.x=gl->pos.x+gl->ex_radius*sx*rnd();
pd->ov.y=gl->pos.y+gl->ex_radius*sy*rnd();
pd->ov.z=gl->pos.z+gl->ex_radius*sz*rnd();
EERIE_3D vect;
vect.x=pd->ov.x-gl->pos.x;
vect.y=pd->ov.y-gl->pos.y;
vect.z=pd->ov.z-gl->pos.z;
TRUEVector_Normalize(&vect);
if (gl->extras & EXTRAS_FIREPLACE)
{
pd->move.x = vect.x * 6.f * gl->ex_speed;
pd->move.y=(-10.f-8.f*rnd())*gl->ex_speed;
pd->move.z = vect.z * 6.f * gl->ex_speed;
}
else
{
pd->move.x = vect.x * 4.f * gl->ex_speed;
pd->move.y=(-10.f-8.f*rnd())*gl->ex_speed;
pd->move.z = vect.z * 4.f * gl->ex_speed;
}
pd->siz=4.f*gl->ex_size*0.3f;
pd->tolive=1200+(unsigned long)(rnd()*500.f*gl->ex_speed);
pd->special=0;//FIRE_TO_SMOKE;
pd->tc = fire2;
pd->special |= ROTATING | MODULATE_ROTATION | GRAVITY;
pd->fparam = 0.1f-rnd()*0.2f*gl->ex_speed;
pd->scale.x = -3.f;
pd->scale.y = -3.f;
pd->scale.z = -3.f;
pd->timcreation = lARXTime;
if (gl->extras & EXTRAS_COLORLEGACY)
{
pd->r=gl->rgb.r;
pd->g=gl->rgb.g;
pd->b=gl->rgb.b;
}
else pd->r=pd->g=pd->b=1.f;
}
}
}
}
else
{
if ((!gl->status) && (gl->sample != ARX_SOUND_INVALID_RESOURCE))
{
ARX_SOUND_Stop(gl->sample);
gl->sample = ARX_SOUND_INVALID_RESOURCE;
}
}
}
}
//-----------------------------------------------------------------------------
void ARX_MAGICAL_FLARES_FirstInit()
{
flarenum=0;
for(long i=0;iflarecount--;
}
flare[i].exist=0;
flare[i].tolive=0;
flarenum--;
if (ValidDynLight(flare[i].dynlight!=-1))
DynLight[flare[i].dynlight].exist=0;
flare[i].dynlight=-1;
}
}
flarenum=0;
}
//-----------------------------------------------------------------------------
void AddFlare(EERIE_S2D * pos,float sm,short typ,INTERACTIVE_OBJ * io)
{
long i;
float vx,vy;
EERIE_CAMERA ka;
float zz;
for (i=0;iexist=1;
fl->bDrawBitmap=0;
if (io)
{
fl->flags=1;
fl->io=io;
io->flarecount++;
}
else
{
fl->flags=0;
fl->io=NULL;
}
flarenum++;
fl->x=pos->x-rnd()*4;
fl->y=pos->y-rnd()*4-50;
fl->tv.rhw=fl->v.rhw=1.f;
fl->tv.specular=fl->v.specular=1;
memcpy(&ka,Kam,sizeof(EERIE_CAMERA));
ka.angle.a=360.f-ka.angle.a;
ka.angle.b=360.f-ka.angle.b;
ka.angle.g=360.f-ka.angle.g;
EERIE_CAMERA * oldcam=ACTIVECAM;
SetActiveCamera(&ka);
PrepareCamera(&ka);
fl->v.sx+=ka.pos.x;
fl->v.sy+=ka.pos.y;
fl->v.sz+=ka.pos.z;
EE_RTT(&fl->tv,&fl->v);
fl->v.sx+=ka.pos.x;
fl->v.sy+=ka.pos.y;
fl->v.sz+=ka.pos.z;
vx=-(fl->x-subj.centerx);
vy=(fl->y-subj.centery);
vx*=0.2173913f;///=4.6f;
vy*=0.1515151515151515f;///=6.6f;
if (io)
{
fl->v.sx=io->pos.x-(float)EEsin(DEG2RAD(MAKEANGLE(io->angle.b+vx)))*100.f;
fl->v.sy=io->pos.y+(float)EEsin(DEG2RAD(MAKEANGLE(io->angle.a+vy)))*100.f-150.f;
fl->v.sz=io->pos.z+(float)EEcos(DEG2RAD(MAKEANGLE(io->angle.b+vx)))*100.f;
}
else
{
fl->v.sz=75.f;
fl->v.sx=((float)(pos->x-(DANAESIZX>>1)))*fl->v.sz*2.f/(float)DANAESIZX;
fl->v.sy=((float)(pos->y-(DANAESIZY>>1)))*fl->v.sz*2.f/((float)DANAESIZY*((float)DANAESIZX/(float)DANAESIZY));
ka=*oldcam;
SetActiveCamera(&ka);
PrepareCamera(&ka);
float temp=(fl->v.sy*-ka.Xsin) + (fl->v.sz*ka.Xcos);
fl->v.sy = (fl->v.sy*ka.Xcos) - (-fl->v.sz*ka.Xsin);
fl->v.sz =(temp*ka.Ycos) - (-fl->v.sx*ka.Ysin);
fl->v.sx = (temp*-ka.Ysin) + (fl->v.sx*ka.Ycos);
fl->v.sx+=oldcam->pos.x;
fl->v.sy+=oldcam->pos.y;
fl->v.sz+=oldcam->pos.z;
}
fl->tv.sx=fl->v.sx;
fl->tv.sy=fl->v.sy;
fl->tv.sz=fl->v.sz;
SetActiveCamera(oldcam);
switch (PIPOrgb)
{
case 0:
fl->g=rnd()*DEUXTIERS;
fl->r=(rnd()*DEUXTIERS)+0.4f;
fl->b=(rnd()*DEUXTIERS)+0.4f;
break;
case 1:
fl->b=rnd()*0.55f;
fl->g=(rnd()*0.625f)+0.5f;
fl->r=(rnd()*0.625f)+0.5f;
break;
case 2:
fl->b=rnd()*0.55f;
fl->g = rnd() * 0.55f;
fl->r=(rnd()*DEUXTIERS)+0.4f;
break;
}
if (typ == -1 )
{
if (EERIEMouseButton & 1) zz = 0.29f;
else if (sm>0.5f) zz=rnd();
else zz=1.f;
if ( zz < 0.2f )
{
fl->type=2;
fl->size=((rnd()*42)+42.f);
fl->tolive=((800.f+rnd()*800.f)*(float)FLARE_MUL);
}
else if ( zz < 0.5f )
{
fl->type=3;
fl->size=((rnd()*52)+16.f);
fl->tolive=((800.f+rnd()*800.f)*(float)FLARE_MUL);
}
else
{
fl->type=1;
fl->size=((rnd()*24)+32.f) *sm;
fl->tolive=((1700.f+rnd()*500.f)*(float)FLARE_MUL);
}
}
else
{
zz=rnd();
if (zz>0.8f) fl->type=1;
else fl->type=4;
fl->size=((rnd()*38)+64.f) *sm;
fl->tolive=((1700.f+rnd()*500.f)*(float)FLARE_MUL);
}
fl->dynlight=-1;
fl->move=OPIPOrgb;
if (!HIDEMAGICDUST)
{
for (long kk=0;kk<3;kk++)
{
long j=ARX_PARTICLES_GetFree();
if ((j!=-1) && (!ARXPausedTimer) && (rnd()*100.f<50.f))
{
ParticleCount++;
PARTICLE_DEF * pd=&particle[j];
pd->special=FADE_IN_AND_OUT | ROTATING | MODULATE_ROTATION | DISSIPATING;
if(!io)
{
pd->special|=PARTICLE_NOZBUFFER;
}
pd->exist = TRUE;
pd->zdec = 0;
pd->ov.x = fl->v.sx+rnd()*10.f-5.f;
pd->ov.y = fl->v.sy+rnd()*10.f-5.f;
pd->ov.z = fl->v.sz+rnd()*10.f-5.f;
pd->move.x = 0.f;
pd->move.y = 5.f;
pd->move.z = 0.f;
pd->scale.x = -2.f;
pd->scale.y = -2.f;
pd->scale.z = -2.f;
pd->timcreation = lARXTime;
pd->tolive = (unsigned long)(float)(1300.f+rnd()*800.f+kk*100.f);
pd->tc = fire2;
if (kk==1)
{
pd->move.y = 5.f - (float)kk;
pd->siz = 1.f + (float)(kk) * DIV2;
}
else pd->siz=1.f+rnd()*1.f;
pd->r=fl->r*DEUXTIERS;
pd->g=fl->g*DEUXTIERS;
pd->b=fl->b*DEUXTIERS;
pd->fparam=1.2f;
}
}
}
return;
}
}
}
//-----------------------------------------------------------------------------
void AddFlare2(EERIE_S2D * pos,float sm,short typ,INTERACTIVE_OBJ * io)
{
long i;
float zz;
for (i=0;iexist=1;
fl->bDrawBitmap=1;
if (io)
{
fl->flags=1;
fl->io=io;
io->flarecount++;
}
else
{
fl->flags=0;
fl->io=NULL;
}
flarenum++;
fl->x=pos->x-rnd()*4;
fl->y=pos->y-rnd()*4-50;
fl->tv.rhw=fl->v.rhw=1.f;
fl->tv.specular=fl->v.specular=1;
fl->tv.sx=fl->x;
fl->tv.sy=fl->y;
fl->tv.sz = 0.001f;
switch (PIPOrgb)
{
case 0:
fl->g=rnd()*DEUXTIERS;
fl->r=(rnd()*DEUXTIERS)+0.4f;
fl->b=(rnd()*DEUXTIERS)+0.4f;
break;
case 1:
fl->b=rnd()*0.55f;
fl->g=(rnd()*0.625f)+0.5f;
fl->r=(rnd()*0.625f)+0.5f;
break;
case 2:
fl->b=rnd()*0.55f;
fl->g = rnd() * 0.55f;
fl->r=(rnd()*DEUXTIERS)+0.4f;
break;
}
if (typ == -1 )
{
if (EERIEMouseButton & 1) zz = 0.29f;
else if (sm>0.5f) zz=rnd();
else zz=1.f;
if ( zz < 0.2f )
{
fl->type=2;
fl->size=((rnd()*42)+42.f);
fl->tolive=((800.f+rnd()*800.f)*(float)FLARE_MUL);
}
else if ( zz < 0.5f )
{
fl->type=3;
fl->size=((rnd()*52)+16.f);
fl->tolive=((800.f+rnd()*800.f)*(float)FLARE_MUL);
}
else
{
fl->type=1;
fl->size=((rnd()*24)+32.f) *sm;
fl->tolive=((1700.f+rnd()*500.f)*(float)FLARE_MUL);
}
}
else
{
zz=rnd();
if (zz>0.8f) fl->type=1;
else fl->type=4;
fl->size=((rnd()*38)+64.f) *sm;
fl->tolive=((1700.f+rnd()*500.f)*(float)FLARE_MUL);
}
fl->dynlight=-1;
fl->move=OPIPOrgb;
if (!HIDEMAGICDUST)
for (long kk=0;kk<3;kk++)
{
long j=ARX_PARTICLES_GetFree();
if ((j!=-1) && (!ARXPausedTimer) && (rnd()*100.f<50.f))
{
ParticleCount++;
PARTICLE_DEF * pd=&particle[j];
pd->special = FADE_IN_AND_OUT;
pd->exist = TRUE;
pd->zdec = 0;
pd->ov.x = fl->v.sx+rnd()*10.f-5.f;
pd->ov.y = fl->v.sy+rnd()*10.f-5.f;
pd->ov.z = fl->v.sz+rnd()*10.f-5.f;
pd->move.x = 0.f;
pd->move.y = 5.f;
pd->move.z = 0.f;
pd->scale.x = -2.f;
pd->scale.y = -2.f;
pd->scale.z = -2.f;
pd->timcreation = lARXTime;
pd->tolive = (unsigned long)(float)(1300.f+rnd()*800.f+kk*100.f);
pd->tc = fire2;
if (kk==1)
{
pd->move.y = 5.f - (float)kk;
pd->siz = 1.f + (float)(kk) * DIV2;
}
else pd->siz=1.f+rnd()*1.f;
pd->r=fl->r*DEUXTIERS;
pd->g=fl->g*DEUXTIERS;
pd->b=fl->b*DEUXTIERS;
pd->fparam=1.2f;
pd->type=PARTICLE_2D;
}
}
i=MAX_FLARES + 1;
}
}
}
//-----------------------------------------------------------------------------
void AddLFlare(float x, float y,INTERACTIVE_OBJ * io)
{
EERIE_S2D pos;
pos.x=(short)x;
pos.y=(short)y;
AddFlare(&pos,0.45f,1,io);
}
//-----------------------------------------------------------------------------
void FlareLine(EERIE_S2D * pos0, EERIE_S2D * pos1, INTERACTIVE_OBJ * io)
{
float dx,dy,adx,ady,m;
long i;
long z;
float x0=pos0->x;
float x1=pos1->x;
float y0=pos0->y;
float y1=pos1->y;
dx=(x1-x0);
adx=EEfabs(dx);
dy=(y1-y0);
ady=EEfabs(dy);
if (adx>ady)
{
if (x0>x1)
{
F2L(x1,&z);
x1=x0;
x0=(float)z;
F2L(y1,&z);
y1=y0;
y0=(float)z;
}
if (x0y1)
{
F2L(x1,&z);
x1=x0;
x0=(float)z;
F2L(y1,&z);
y1=y0;
y0=(float)z;
}
if (y0