From 3609bf4df885b57e7b601489ee7d7b37af59f4d8 Mon Sep 17 00:00:00 2001 From: iamthesenate1 Date: Sun, 26 Dec 2021 13:17:09 +0200 Subject: [PATCH] Some optimisations --- Sources/Depend/Dependency.cpp | 7 +- Sources/Engine/Base/FileName.cpp | 4 +- Sources/Engine/Base/Shell.cpp | 19 +- Sources/Engine/Base/Unzip.cpp | 5 +- Sources/Engine/GameAgent/GameAgent.cpp | 14 +- Sources/Engine/Light/LayerMixer.cpp | 3 +- Sources/Engine/Math/Object3D_CSG.cpp | 4 +- Sources/Engine/Network/ClientInterface.cpp | 3 - Sources/Engine/Network/EMsgBuffer.h | 7 +- Sources/Engine/Network/EntityHashing.h | 2 +- Sources/Engine/Network/Network.cpp | 4 +- Sources/Engine/Rendering/SelectOnRender.cpp | 3 +- Sources/Engine/Terrain/TerrainRayCasting.cpp | 4 +- Sources/EngineGui/EngineGUI.cpp | 2 +- Sources/Entities/Common/Common.h | 423 +- Sources/Entities/Common/HUD.cpp | 2216 +++---- Sources/Entities/Common/Particles.cpp | 5972 +++++++++--------- Sources/Entities/Common/PathFinding.cpp | 555 +- Sources/EntitiesMP/Common/Common.h | 9 +- Sources/EntitiesMP/Common/HUD.cpp | 2 +- Sources/EntitiesMP/Common/Particles.cpp | 9 +- Sources/GameMP/Game.cpp | 3 +- Sources/GameMP/Game.h | 4 +- 23 files changed, 4610 insertions(+), 4664 deletions(-) diff --git a/Sources/Depend/Dependency.cpp b/Sources/Depend/Dependency.cpp index c923c25..624cbc2 100644 --- a/Sources/Depend/Dependency.cpp +++ b/Sources/Depend/Dependency.cpp @@ -29,12 +29,7 @@ void AdjustFilePath_t(CTFileName &fnm) } // class constructor -CDependInfo::CDependInfo(CTFileName fnFileName, CTFileName fnParent) -{ - // copy file name - di_fnFileName = fnFileName; - di_fnParent = fnParent; -} +CDependInfo::CDependInfo(CTFileName fnFileName, CTFileName fnParent): /*copy file name*/ di_fnFileName(fnFileName), di_fnParent(fnParent){} BOOL CDependInfo::IsFileOnDiskUpdated(void) { diff --git a/Sources/Engine/Base/FileName.cpp b/Sources/Engine/Base/FileName.cpp index ffd30b4..a036e73 100644 --- a/Sources/Engine/Base/FileName.cpp +++ b/Sources/Engine/Base/FileName.cpp @@ -37,7 +37,7 @@ const char *CTFileName::convertFromWin32(const char *src) static const char *dirsep = NULL; static size_t seplen = 0; static char buf[MAX_PATH]; // This is NOT thread safe, fyi. - char *dest = buf; + char *dest; if (src == NULL) { @@ -78,7 +78,7 @@ const char *CTFileName::convertToWin32(const char *src) static const char *dirsep = NULL; static size_t seplen = 0; static char buf[MAX_PATH]; // This is NOT thread safe, fyi. - char *dest = buf; + char *dest; if (src == NULL) { diff --git a/Sources/Engine/Base/Shell.cpp b/Sources/Engine/Base/Shell.cpp index 2611528..3fe98ea 100644 --- a/Sources/Engine/Base/Shell.cpp +++ b/Sources/Engine/Base/Shell.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2002-2012 Croteam Ltd. +/* Copyright (c) 2002-2012 Croteam Ltd. This program is free software; you can redistribute it and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation @@ -182,6 +182,7 @@ CTString ScriptEsc(const CTString &str) #pragma inline_depth(0) void MakeAccessViolation(void* pArgs) + { INDEX bDont = NEXTARGUMENT(INDEX); if( bDont) return; @@ -674,7 +675,7 @@ FLOAT CShell::GetFLOAT(const CTString &strName) // error ASSERT(FALSE); return -666.0f; - } + } // get it return *(FLOAT*)pss->ss_pvValue; } @@ -688,7 +689,7 @@ void CShell::SetFLOAT(const CTString &strName, FLOAT fValue) // error ASSERT(FALSE); return; - } + } // set it *(FLOAT*)pss->ss_pvValue = fValue; } @@ -703,7 +704,7 @@ INDEX CShell::GetINDEX(const CTString &strName) // error ASSERT(FALSE); return -666; - } + } // get it return *(INDEX*)pss->ss_pvValue; } @@ -717,7 +718,7 @@ void CShell::SetINDEX(const CTString &strName, INDEX iValue) // error ASSERT(FALSE); return; - } + } // set it *(INDEX*)pss->ss_pvValue = iValue; } @@ -732,7 +733,7 @@ CTString CShell::GetString(const CTString &strName) // error ASSERT(FALSE); return ""; - } + } // get it return *(CTString*)pss->ss_pvValue; } @@ -746,7 +747,7 @@ void CShell::SetString(const CTString &strName, const CTString &strValue) // error ASSERT(FALSE); return; - } + } // set it *(CTString*)pss->ss_pvValue = strValue; } @@ -762,7 +763,7 @@ CTString CShell::GetValue(const CTString &strName) // error ASSERT(FALSE); return ""; - } + } // get it ShellTypeType stt = _shell_ast[pss->ss_istType].st_sttType; @@ -795,7 +796,7 @@ void CShell::SetValue(const CTString &strName, const CTString &strValue) // error ASSERT(FALSE); return; - } + } // get it ShellTypeType stt = _shell_ast[pss->ss_istType].st_sttType; switch(stt) { diff --git a/Sources/Engine/Base/Unzip.cpp b/Sources/Engine/Base/Unzip.cpp index 66df7a8..042a30f 100644 --- a/Sources/Engine/Base/Unzip.cpp +++ b/Sources/Engine/Base/Unzip.cpp @@ -166,11 +166,8 @@ CTString GetZlibError(int ierr) } } -CZipHandle::CZipHandle(void) +CZipHandle::CZipHandle(void): zh_bOpen(FALSE), zh_fFile(NULL), zh_pubBufIn(NULL) { - zh_bOpen = FALSE; - zh_fFile = NULL; - zh_pubBufIn = NULL; memset(&zh_zstream, 0, sizeof(zh_zstream)); } void CZipHandle::Clear(void) diff --git a/Sources/Engine/GameAgent/GameAgent.cpp b/Sources/Engine/GameAgent/GameAgent.cpp index f459d25..a5eb0ab 100644 --- a/Sources/Engine/GameAgent/GameAgent.cpp +++ b/Sources/Engine/GameAgent/GameAgent.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2002-2012 Croteam Ltd. +/* Copyright (c) 2002-2012 Croteam Ltd. This program is free software; you can redistribute it and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation @@ -593,7 +593,7 @@ extern void GameAgent_EnumTrigger(BOOL bInternet) if ( _pNetwork->ga_bEnumerationChange ) { return; } - + if ( !bInternet && ga_bMSLegacy) { // make sure that there are no requests still stuck in buffer ga_asrRequests.Clear(); @@ -866,7 +866,7 @@ extern void GameAgent_EnumTrigger(BOOL bInternet) _bActivated = TRUE; _bInitialized = TRUE; _initializeWinsock(); - + } } } @@ -1051,7 +1051,7 @@ extern void GameAgent_EnumUpdate(void) pthread_detach(_hThread); } _bActivatedLocal = FALSE; - } + } #else /* MSLegacy */ if(_bActivated) { @@ -1152,7 +1152,7 @@ void* _MS_Thread(void *arg) { /** do recvfrom stuff **/ iRet = recvfrom(_sockudp, _szBuffer, 2048, 0, (sockaddr*)&_sinClient, &_iClientLength); FD_CLR(_sockudp, &readfds_udp); - if(iRet != -1 && iRet > 100 && iRet != SOCKET_ERROR) { + if(iRet > 100 && iRet != SOCKET_ERROR) { // null terminate the buffer _szBuffer[iRet] = 0; char *sPch = NULL; @@ -1360,7 +1360,7 @@ void* _LocalNet_Thread(void *arg) { /** do recvfrom stuff **/ iRet = recvfrom(_sockudp, _szBuffer, 2048, 0, (sockaddr*)&_sinClient, &_iClientLength); FD_CLR(_sockudp, &readfds_udp); - if(iRet != -1 && iRet > 100 && iRet != SOCKET_ERROR) { + if(iRet > 100 && iRet != SOCKET_ERROR) { // null terminate the buffer _szBuffer[iRet] = 0; char *sPch = NULL; @@ -1370,7 +1370,7 @@ void* _LocalNet_Thread(void *arg) { if(_szIPPortBufferLocal != NULL) { delete[] _szIPPortBufferLocal; } - _szIPPortBufferLocal = NULL; + _szIPPortBufferLocal = NULL; WSACleanup(); return 0; } else { diff --git a/Sources/Engine/Light/LayerMixer.cpp b/Sources/Engine/Light/LayerMixer.cpp index 8fcf6be..e7daa71 100755 --- a/Sources/Engine/Light/LayerMixer.cpp +++ b/Sources/Engine/Light/LayerMixer.cpp @@ -2002,9 +2002,8 @@ void CLayerMixer::MixOneMipmapDynamic( CBrushShadowMap *pbsm, INDEX iMipmap) // constructor -CLayerMixer::CLayerMixer( CBrushShadowMap *pbsm, INDEX iFirstMip, INDEX iLastMip, BOOL bDynamic) +CLayerMixer::CLayerMixer( CBrushShadowMap *pbsm, INDEX iFirstMip, INDEX iLastMip, BOOL bDynamic): lm_bDynamic(bDynamic) { - lm_bDynamic = bDynamic; if( bDynamic) { // check dynamic layers for complete blackness BOOL bAllBlack = TRUE; diff --git a/Sources/Engine/Math/Object3D_CSG.cpp b/Sources/Engine/Math/Object3D_CSG.cpp index 98bc4a3..26e70c7 100644 --- a/Sources/Engine/Math/Object3D_CSG.cpp +++ b/Sources/Engine/Math/Object3D_CSG.cpp @@ -195,9 +195,7 @@ public: // array for holding edges that proceed with testing CDynamicArray oc_abedProceeding; - CObjectCSG(void) { - oc_bCSGIngoringEnabled = FALSE; - oc_bSkipObjectB = FALSE; + CObjectCSG(void): oc_bCSGIngoringEnabled(FALSE), oc_bSkipObjectB(FALSE){ } /* Add an entire array of BSP edges to some polygon according to action code. */ diff --git a/Sources/Engine/Network/ClientInterface.cpp b/Sources/Engine/Network/ClientInterface.cpp index f07acfb..a4f2e42 100644 --- a/Sources/Engine/Network/ClientInterface.cpp +++ b/Sources/Engine/Network/ClientInterface.cpp @@ -480,9 +480,6 @@ BOOL CClientInterface::UpdateInputBuffers(void) // take this packet out of the input buffer ci_pbInputBuffer.RemovePacket(ppaPacket->pa_ulSequence,FALSE); - if (ppaPacket->pa_ulSequence == 8) { - ppaPacket->pa_ulSequence = 8; - } // a packet can be accepted from the broadcast ID only if it is an acknowledge packet or // if it is a connection confirmation response packet and the client isn't already connected if (ppaPacket->pa_adrAddress.adr_uwID == SLASHSLASH || ppaPacket->pa_adrAddress.adr_uwID == 0) { diff --git a/Sources/Engine/Network/EMsgBuffer.h b/Sources/Engine/Network/EMsgBuffer.h index 1c33c90..e957962 100644 --- a/Sources/Engine/Network/EMsgBuffer.h +++ b/Sources/Engine/Network/EMsgBuffer.h @@ -81,12 +81,7 @@ struct TickMarker { UBYTE tm_ubAcknowledgesExpected; UWORD tm_uwNumMessages; - TickMarker() { - tm_fTickTime = -1; - tm_slTickOffset = -1; - tm_ubAcknowledgesExpected = 0; - tm_uwNumMessages = 0; - } + TickMarker(): tm_fTickTime(-1), tm_fTickTime(-1), tm_ubAcknowledgesExpected(0), tm_uwNumMessages (0){} }; diff --git a/Sources/Engine/Network/EntityHashing.h b/Sources/Engine/Network/EntityHashing.h index f515851..73d34df 100644 --- a/Sources/Engine/Network/EntityHashing.h +++ b/Sources/Engine/Network/EntityHashing.h @@ -47,7 +47,7 @@ public: CEntityPointer ehi_epEntityPointer; CClientEntry ehi_ceClientEntries[SERVER_CLIENTS]; - CEntityHashItem() {ehi_ulEntityID = -1;} // entity pointer will initialize itself to NULL + CEntityHashItem(): ehi_ulEntityID(-1){} // entity pointer will initialize itself to NULL ~CEntityItem() {}; // entity poiner will destroy itself and remove the reference diff --git a/Sources/Engine/Network/Network.cpp b/Sources/Engine/Network/Network.cpp index d283a1a..a5c25ba 100644 --- a/Sources/Engine/Network/Network.cpp +++ b/Sources/Engine/Network/Network.cpp @@ -185,9 +185,7 @@ public: ~CGatherCRC(); }; -CGatherCRC::CGatherCRC() { - bOld = CRCT_bGatherCRCs; -} +CGatherCRC::CGatherCRC(): bOld(CRCT_bGatherCRCs){} CGatherCRC::~CGatherCRC() { CRCT_bGatherCRCs = bOld; } diff --git a/Sources/Engine/Rendering/SelectOnRender.cpp b/Sources/Engine/Rendering/SelectOnRender.cpp index 561cb3b..41a75cc 100644 --- a/Sources/Engine/Rendering/SelectOnRender.cpp +++ b/Sources/Engine/Rendering/SelectOnRender.cpp @@ -165,8 +165,7 @@ void SelectVertexOnRender(CBrushVertex &bvx, const PIX2D &vpix) // if selecting with lasso } else { // if the vertex is set in lasso buffer - if (_pubLassoBuffer!=NULL - &&_pubLassoBuffer[vpix(2)*_pixSizeI+vpix(1)]) { + if (_pubLassoBuffer[vpix(2)*_pixSizeI+vpix(1)]) { // if alternative if (_bSelectAlternative) { diff --git a/Sources/Engine/Terrain/TerrainRayCasting.cpp b/Sources/Engine/Terrain/TerrainRayCasting.cpp index 8fe9eed..9fa4a38 100755 --- a/Sources/Engine/Terrain/TerrainRayCasting.cpp +++ b/Sources/Engine/Terrain/TerrainRayCasting.cpp @@ -186,11 +186,9 @@ static FLOAT HitCheckQuad(const PIX ix, const PIX iz) // if the polygon is intersected by the ray, and it is the closest intersection so far if (isIntersector.IsIntersecting() && (fHitDistance < fDistance)) { // remember hit coordinates - if(fHitDistance= 0) && (iDlgResult <= 2) ) + if( (iDlgResult >= 0) && (iDlgResult <= 2) ) { // if result is 2 we want to create effect texture if( iDlgResult == 2) diff --git a/Sources/Entities/Common/Common.h b/Sources/Entities/Common/Common.h index 14fc1f3..6b5079d 100644 --- a/Sources/Entities/Common/Common.h +++ b/Sources/Entities/Common/Common.h @@ -1,215 +1,208 @@ -// common headers for flesh entity classes - -#include /* rcg10062001 need enum definition... */ -#include /* rcg10062001 need enum definition... */ - -#define SURFACE_SAND 9 -#define SURFACE_WATER 12 -#define SURFACE_RED_SAND 13 - -// Max ammo -#define MAX_BULLETS INDEX(500) -#define MAX_SHELLS INDEX(100) -#define MAX_ROCKETS INDEX(50) -#define MAX_GRENADES INDEX(50) -//#define MAX_NAPALM INDEX(250) -#define MAX_ELECTRICITY INDEX(400) -#define MAX_IRONBALLS INDEX(30) -//#define MAX_NUKEBALLS INDEX(3) - -// Bit shifters for ammo -#define AMMO_BULLETS 0 -#define AMMO_SHELLS 1 -#define AMMO_ROCKETS 2 -#define AMMO_GRENADES 3 -//#define AMMO_NAPALM 4 -#define AMMO_ELECTRICITY 5 -//#define AMMO_NUKEBALLS 6 -#define AMMO_IRONBALLS 7 - - -// Ammo mana Value -#define AV_SHELLS INDEX(70) -#define AV_BULLETS INDEX(10) -#define AV_ROCKETS INDEX(150) -#define AV_GRENADES INDEX(150) -#define AV_ELECTRICITY INDEX(250) -#define AV_IRONBALLS INDEX(700) -//#define AV_NUKEBALLS INDEX(1800) -//#define AV_NAPALM INDEX(200) - -enum EmptyShellType { - ESL_BULLET = 0, - ESL_SHOTGUN = 1, - ESL_BUBBLE = 2, - ESL_BULLET_SMOKE = 3, - ESL_SHOTGUN_SMOKE = 4, - ESL_COLT_SMOKE = 5, -}; -// empty shell launch info -#define MAX_FLYING_SHELLS 32 -struct ShellLaunchData { - FLOAT sld_fSize; // size multiplier - FLOAT3D sld_vPos; // launch position - FLOAT3D sld_vSpeed; // launch speed - FLOAT3D sld_vUp; // up vector in moment of launch - FLOAT sld_tmLaunch; // time of launch - EmptyShellType sld_estType; // shell type -}; -#define ShellLaunchData_array m_asldData[MAX_FLYING_SHELLS] - -// world change -struct WorldChange { - CTString strGroup; // group name - CPlacement3D plLink; // link placement for relative change - INDEX iType; // change type -}; -extern struct WorldChange _SwcWorldChange; - -// entity info -struct EntityInfo { - EntityInfoBodyType Eeibt; // body type - FLOAT fMass; // mass (in kg) - FLOAT vSourceCenter[3]; // body point (offset from handle) when entity look another entity - FLOAT vTargetCenter[3]; // body point (offset from handle) when entity is target of look -}; - -// entity info -struct EntityStats { - CTString es_strName; - INDEX es_ctCount; - INDEX es_ctAmmount; - FLOAT es_fValue; - INDEX es_iScore; - inline void Clear() { es_strName.Clear(); } -}; - -// statistics data for player stats management -struct DECL_DLL PlayerStats { - INDEX ps_iScore; - INDEX ps_iKills; - INDEX ps_iDeaths; - INDEX ps_iSecrets; - TIME ps_tmTime; - - PlayerStats(void) - { - ps_iScore = 0; - ps_iKills = 0; - ps_iDeaths = 0; - ps_iSecrets = 0; - ps_tmTime = 0.0f; - } -}; - -// get info position for entity -DECL_DLL void GetEntityInfoPosition(CEntity *pen, FLOAT *pf, FLOAT3D &vPos); -// get source and target positions for ray cast -DECL_DLL void GetPositionCastRay(CEntity *penSource, CEntity *penTarget, FLOAT3D &vSource, FLOAT3D &vTarget); - -// set bool from bool enum type -DECL_DLL void SetBoolFromBoolEType(BOOL &bSet, BoolEType bet); -// send event to target -DECL_DLL void SendToTarget(CEntity *penSendEvent, EventEType eetEventType, CEntity *penCaused = NULL); -// send event in range -DECL_DLL void SendInRange(CEntity *penSource, EventEType eetEventType, const FLOATaabbox3D &boxRange); - -// spawn reminder -DECL_DLL CEntityPointer SpawnReminder(CEntity *penOwner, FLOAT fWaitTime, INDEX iValue); -// spawn flame -//CEntityPointer SpawnFlame(CEntity *penOwner, CEntity *penAttach, const FLOAT3D &vSource); - -// Set components -DECL_DLL void SetComponents(CEntity *pen, CModelObject &mo, ULONG ulIDModel, ULONG ulIDTexture, - ULONG ulIDReflectionTexture, ULONG ulIDSpecularTexture, ULONG ulIDBumpTexture); -// Add attachment to model -DECL_DLL void AddAttachmentToModel(CEntity *pen, CModelObject &mo, INDEX iAttachment, ULONG ulIDModel, ULONG ulIDTexture, - ULONG ulIDReflectionTexture, ULONG ulIDSpecularTexture, ULONG ulIDBumpTexture); -// Remove attachment from model -DECL_DLL void RemoveAttachmentFromModel(CModelObject &mo, INDEX iAttachment); - -// Kick entity -DECL_DLL void KickEntity(CEntity *penTarget, FLOAT3D vSpeed); - - -// lens flare variables -extern CLensFlareType _lftStandard; -extern CLensFlareType _lftStandardReflections; -extern CLensFlareType _lftYellowStarRedRing; -extern CLensFlareType _lftYellowStarRedRingFar; -extern CLensFlareType _lftWhiteGlowStarRedRing; -extern CLensFlareType _lftWhiteGlowStar; -extern CLensFlareType _lftWhiteGlowStarNG; -extern CLensFlareType _lftWhiteStarRedRingStreaks; -extern CLensFlareType _lftWhiteStarRedReflections; -extern CLensFlareType _lftBlueStarBlueReflections; -extern CLensFlareType _lftProjectileStarGlow; -extern CLensFlareType _lftProjectileWhiteBubbleGlow; -extern CLensFlareType _lftProjectileYellowBubbleGlow; -extern CLensFlareType _lftPVSpaceShipWindowFlare; -extern CLensFlareType _lftCatmanFireGlow; -extern CLensFlareType _lftWhiteGlowFar; -// init lens flare effects -void InitLensFlares(void); -// close lens flares effects -void CloseLensFlares(void); - -DECL_DLL BOOL SetPlayerAppearance(CModelObject *mo, CPlayerCharacter *ppc, CTString &strName, BOOL bPreview); - -// debugging functions -DECL_DLL const char *PrintConsole(void); -DECL_DLL const char *PrintStack(CEntity *pen); - -// debris spawning -DECL_DLL void Debris_Begin( - EntityInfoBodyType Eeibt, - enum DebrisParticlesType dptParticles, - enum BasicEffectType betStain, - FLOAT fEntitySize, // entity size in meters - const FLOAT3D &vSpeed, - const FLOAT3D &vSpawnerSpeed, // how fast was the entity moving - const FLOAT fConeSize, // size multiplier for debris cone - const FLOAT fSpeedUp, // size multiplier for debris catapulting up (0-no multiply) - const COLOR colDebris=C_WHITE // multiply color -); -DECL_DLL CEntityPointer Debris_Spawn( - CEntity *penSpawner, - CEntity *penComponents, - SLONG idModelComponent, - SLONG idTextureComponent, - SLONG idReflectionTextureComponent, - SLONG idSpecularTextureComponent, - SLONG idBumpTextureComponent, - INDEX iModelAnim, - FLOAT fSize, // size relative to entity size (or 0 for absolute stretch of 1) - const FLOAT3D &vPosRatio); - -// get default entity info for given body type -DECL_DLL EntityInfo *GetStdEntityInfo(EntityInfoBodyType eibt); -// damage control functions -DECL_DLL FLOAT DamageStrength(EntityInfoBodyType eibtBody, enum DamageType dtDamage); - -// Print center screen message -DECL_DLL void PrintCenterMessage(CEntity *penThis, CEntity *penTarget, - const CTString &strMessage, TIME tmLength, enum MessageSound mssSound); - -// get name of a key item -DECL_DLL const char *GetKeyName(enum KeyItemType kit); - -// get session properties -DECL_DLL inline const CSessionProperties *GetSP(void) -{ - return ((const CSessionProperties *)_pNetwork->GetSessionProperties()); -} - -// i.e. weapon sound when fireing or exploding -DECL_DLL void SpawnRangeSound( CEntity *penPlayer, CEntity *penPos, enum SoundType st, FLOAT fRange); - -// get some player for trigger source if any is existing -DECL_DLL CEntity *FixupCausedToPlayer(CEntity *penThis, CEntity *penCaused, BOOL bWarning=TRUE); - -// precisely lerp between two placement using quaternions -DECL_DLL CPlacement3D LerpPlacementsPrecise(const CPlacement3D &pl0, const CPlacement3D &pl1, FLOAT fRatio); - -// obtain game extra damage per enemy and per player -DECL_DLL FLOAT GetGameDamageMultiplier(void); +// common headers for flesh entity classes + +#include /* rcg10062001 need enum definition... */ +#include /* rcg10062001 need enum definition... */ + +#define SURFACE_SAND 9 +#define SURFACE_WATER 12 +#define SURFACE_RED_SAND 13 + +// Max ammo +#define MAX_BULLETS INDEX(500) +#define MAX_SHELLS INDEX(100) +#define MAX_ROCKETS INDEX(50) +#define MAX_GRENADES INDEX(50) +//#define MAX_NAPALM INDEX(250) +#define MAX_ELECTRICITY INDEX(400) +#define MAX_IRONBALLS INDEX(30) +//#define MAX_NUKEBALLS INDEX(3) + +// Bit shifters for ammo +#define AMMO_BULLETS 0 +#define AMMO_SHELLS 1 +#define AMMO_ROCKETS 2 +#define AMMO_GRENADES 3 +//#define AMMO_NAPALM 4 +#define AMMO_ELECTRICITY 5 +//#define AMMO_NUKEBALLS 6 +#define AMMO_IRONBALLS 7 + + +// Ammo mana Value +#define AV_SHELLS INDEX(70) +#define AV_BULLETS INDEX(10) +#define AV_ROCKETS INDEX(150) +#define AV_GRENADES INDEX(150) +#define AV_ELECTRICITY INDEX(250) +#define AV_IRONBALLS INDEX(700) +//#define AV_NUKEBALLS INDEX(1800) +//#define AV_NAPALM INDEX(200) + +enum EmptyShellType { + ESL_BULLET = 0, + ESL_SHOTGUN = 1, + ESL_BUBBLE = 2, + ESL_BULLET_SMOKE = 3, + ESL_SHOTGUN_SMOKE = 4, + ESL_COLT_SMOKE = 5, +}; +// empty shell launch info +#define MAX_FLYING_SHELLS 32 +struct ShellLaunchData { + FLOAT sld_fSize; // size multiplier + FLOAT3D sld_vPos; // launch position + FLOAT3D sld_vSpeed; // launch speed + FLOAT3D sld_vUp; // up vector in moment of launch + FLOAT sld_tmLaunch; // time of launch + EmptyShellType sld_estType; // shell type +}; +#define ShellLaunchData_array m_asldData[MAX_FLYING_SHELLS] + +// world change +struct WorldChange { + CTString strGroup; // group name + CPlacement3D plLink; // link placement for relative change + INDEX iType; // change type +}; +extern struct WorldChange _SwcWorldChange; + +// entity info +struct EntityInfo { + EntityInfoBodyType Eeibt; // body type + FLOAT fMass; // mass (in kg) + FLOAT vSourceCenter[3]; // body point (offset from handle) when entity look another entity + FLOAT vTargetCenter[3]; // body point (offset from handle) when entity is target of look +}; + +// entity info +struct EntityStats { + CTString es_strName; + INDEX es_ctCount; + INDEX es_ctAmmount; + FLOAT es_fValue; + INDEX es_iScore; + inline void Clear() { es_strName.Clear(); } +}; + +// statistics data for player stats management +struct DECL_DLL PlayerStats { + INDEX ps_iScore; + INDEX ps_iKills; + INDEX ps_iDeaths; + INDEX ps_iSecrets; + TIME ps_tmTime; + + PlayerStats(void): ps_iScore(0), ps_iKills(0), ps_iDeaths(0), ps_iSecrets(0), ps_tmTime(0.0f){} +}; + +// get info position for entity +DECL_DLL void GetEntityInfoPosition(CEntity *pen, FLOAT *pf, FLOAT3D &vPos); +// get source and target positions for ray cast +DECL_DLL void GetPositionCastRay(CEntity *penSource, CEntity *penTarget, FLOAT3D &vSource, FLOAT3D &vTarget); + +// set bool from bool enum type +DECL_DLL void SetBoolFromBoolEType(BOOL &bSet, BoolEType bet); +// send event to target +DECL_DLL void SendToTarget(CEntity *penSendEvent, EventEType eetEventType, CEntity *penCaused = NULL); +// send event in range +DECL_DLL void SendInRange(CEntity *penSource, EventEType eetEventType, const FLOATaabbox3D &boxRange); + +// spawn reminder +DECL_DLL CEntityPointer SpawnReminder(CEntity *penOwner, FLOAT fWaitTime, INDEX iValue); +// spawn flame +//CEntityPointer SpawnFlame(CEntity *penOwner, CEntity *penAttach, const FLOAT3D &vSource); + +// Set components +DECL_DLL void SetComponents(CEntity *pen, CModelObject &mo, ULONG ulIDModel, ULONG ulIDTexture, + ULONG ulIDReflectionTexture, ULONG ulIDSpecularTexture, ULONG ulIDBumpTexture); +// Add attachment to model +DECL_DLL void AddAttachmentToModel(CEntity *pen, CModelObject &mo, INDEX iAttachment, ULONG ulIDModel, ULONG ulIDTexture, + ULONG ulIDReflectionTexture, ULONG ulIDSpecularTexture, ULONG ulIDBumpTexture); +// Remove attachment from model +DECL_DLL void RemoveAttachmentFromModel(CModelObject &mo, INDEX iAttachment); + +// Kick entity +DECL_DLL void KickEntity(CEntity *penTarget, FLOAT3D vSpeed); + + +// lens flare variables +extern CLensFlareType _lftStandard; +extern CLensFlareType _lftStandardReflections; +extern CLensFlareType _lftYellowStarRedRing; +extern CLensFlareType _lftYellowStarRedRingFar; +extern CLensFlareType _lftWhiteGlowStarRedRing; +extern CLensFlareType _lftWhiteGlowStar; +extern CLensFlareType _lftWhiteGlowStarNG; +extern CLensFlareType _lftWhiteStarRedRingStreaks; +extern CLensFlareType _lftWhiteStarRedReflections; +extern CLensFlareType _lftBlueStarBlueReflections; +extern CLensFlareType _lftProjectileStarGlow; +extern CLensFlareType _lftProjectileWhiteBubbleGlow; +extern CLensFlareType _lftProjectileYellowBubbleGlow; +extern CLensFlareType _lftPVSpaceShipWindowFlare; +extern CLensFlareType _lftCatmanFireGlow; +extern CLensFlareType _lftWhiteGlowFar; +// init lens flare effects +void InitLensFlares(void); +// close lens flares effects +void CloseLensFlares(void); + +DECL_DLL BOOL SetPlayerAppearance(CModelObject *mo, CPlayerCharacter *ppc, CTString &strName, BOOL bPreview); + +// debugging functions +DECL_DLL const char *PrintConsole(void); +DECL_DLL const char *PrintStack(CEntity *pen); + +// debris spawning +DECL_DLL void Debris_Begin( + EntityInfoBodyType Eeibt, + enum DebrisParticlesType dptParticles, + enum BasicEffectType betStain, + FLOAT fEntitySize, // entity size in meters + const FLOAT3D &vSpeed, + const FLOAT3D &vSpawnerSpeed, // how fast was the entity moving + const FLOAT fConeSize, // size multiplier for debris cone + const FLOAT fSpeedUp, // size multiplier for debris catapulting up (0-no multiply) + const COLOR colDebris=C_WHITE // multiply color +); +DECL_DLL CEntityPointer Debris_Spawn( + CEntity *penSpawner, + CEntity *penComponents, + SLONG idModelComponent, + SLONG idTextureComponent, + SLONG idReflectionTextureComponent, + SLONG idSpecularTextureComponent, + SLONG idBumpTextureComponent, + INDEX iModelAnim, + FLOAT fSize, // size relative to entity size (or 0 for absolute stretch of 1) + const FLOAT3D &vPosRatio); + +// get default entity info for given body type +DECL_DLL EntityInfo *GetStdEntityInfo(EntityInfoBodyType eibt); +// damage control functions +DECL_DLL FLOAT DamageStrength(EntityInfoBodyType eibtBody, enum DamageType dtDamage); + +// Print center screen message +DECL_DLL void PrintCenterMessage(CEntity *penThis, CEntity *penTarget, + const CTString &strMessage, TIME tmLength, enum MessageSound mssSound); + +// get name of a key item +DECL_DLL const char *GetKeyName(enum KeyItemType kit); + +// get session properties +DECL_DLL inline const CSessionProperties *GetSP(void) +{ + return ((const CSessionProperties *)_pNetwork->GetSessionProperties()); +} + +// i.e. weapon sound when fireing or exploding +DECL_DLL void SpawnRangeSound( CEntity *penPlayer, CEntity *penPos, enum SoundType st, FLOAT fRange); + +// get some player for trigger source if any is existing +DECL_DLL CEntity *FixupCausedToPlayer(CEntity *penThis, CEntity *penCaused, BOOL bWarning=TRUE); + +// precisely lerp between two placement using quaternions +DECL_DLL CPlacement3D LerpPlacementsPrecise(const CPlacement3D &pl0, const CPlacement3D &pl1, FLOAT fRatio); + +// obtain game extra damage per enemy and per player +DECL_DLL FLOAT GetGameDamageMultiplier(void); diff --git a/Sources/Entities/Common/HUD.cpp b/Sources/Entities/Common/HUD.cpp index a776e57..fd1db27 100644 --- a/Sources/Entities/Common/HUD.cpp +++ b/Sources/Entities/Common/HUD.cpp @@ -1,1108 +1,1108 @@ - -#include "../StdH/StdH.h" - -#include -#include -#include -#include -#include -#include - - -// armor & health constants -// NOTE: these _do not_ reflect easy/tourist maxvalue adjustments. that is by design! -#define TOP_ARMOR 100 -#define TOP_HEALTH 100 - - -// cheats -extern INDEX cht_bEnable; -extern INDEX cht_bGod; -extern INDEX cht_bFly; -extern INDEX cht_bGhost; -extern INDEX cht_bInvisible; -extern FLOAT cht_fTranslationMultiplier; - -// interface control -extern INDEX hud_bShowInfo; -extern INDEX hud_bShowLatency; -extern INDEX hud_bShowMessages; -extern INDEX hud_iShowPlayers; -extern INDEX hud_iSortPlayers; -extern FLOAT hud_fOpacity; -extern FLOAT hud_fScaling; -extern FLOAT hud_tmWeaponsOnScreen; - - -// player statistics sorting keys -enum SortKeys { - PSK_NAME = 1, - PSK_HEALTH = 2, - PSK_SCORE = 3, - PSK_MANA = 4, - PSK_FRAGS = 5, - PSK_DEATHS = 6, -}; - -// where is the bar lowest value -enum BarOrientations { - BO_LEFT = 1, - BO_RIGHT = 2, - BO_UP = 3, - BO_DOWN = 4, -}; - - - -// maximal mana for master status -#define MANA_MASTER 10000 - -// drawing variables -static const CPlayer *_penPlayer; -static CPlayerWeapons *_penWeapons; -static CDrawPort *_pDP; -static PIX _pixDPWidth, _pixDPHeight; -static FLOAT _fResolutionScaling; -static FLOAT _fCustomScaling; -static ULONG _ulAlphaHUD; -static COLOR _colHUD; -static TIME _tmNow = -1.0f; -static CFontData _fdNumbersFont; - -// array for pointers of all players -CPlayer *_apenPlayers[NET_MAXGAMEPLAYERS] = {0}; - -// status bar textures -static CTextureObject _toHealth; -static CTextureObject _toArmor; -static CTextureObject _toOxygen; -static CTextureObject _toScore; -static CTextureObject _toHiScore; -static CTextureObject _toMessage; -static CTextureObject _toMana; -static CTextureObject _toFrags; -static CTextureObject _toDeaths; -// ammo textures -static CTextureObject _toAShells; -static CTextureObject _toABullets; -static CTextureObject _toARockets; -static CTextureObject _toAGrenades; -static CTextureObject _toANapalm; -static CTextureObject _toAElectricity; -static CTextureObject _toAIronBall; -// weapon textures -static CTextureObject _toWKnife; -static CTextureObject _toWColt; -static CTextureObject _toWSingleShotgun; -static CTextureObject _toWDoubleShotgun; -static CTextureObject _toWTommygun; -static CTextureObject _toWMinigun; -static CTextureObject _toWRocketLauncher; -static CTextureObject _toWGrenadeLauncher; -static CTextureObject _toWPipeBomb; -static CTextureObject _toWFlamer; -static CTextureObject _toWGhostBuster; -static CTextureObject _toWLaser; -static CTextureObject _toWIronCannon; -// tile texture (one has corners, edges and center) -static CTextureObject _toTile; - - -// all info about color transitions -struct ColorTransitionTable { - COLOR ctt_colFine; // color for values over 1.0 - COLOR ctt_colHigh; // color for values from 1.0 to 'fMedium' - COLOR ctt_colMedium; // color for values from 'fMedium' to 'fLow' - COLOR ctt_colLow; // color for values under fLow - FLOAT ctt_fMediumHigh; // when to switch to high color (normalized float!) - FLOAT ctt_fLowMedium; // when to switch to medium color (normalized float!) - BOOL ctt_bSmooth; // should colors have smooth transition -}; -static struct ColorTransitionTable _cttHUD; - - -// ammo's info structure -struct AmmoInfo { - CTextureObject *ai_ptoAmmo; - struct WeaponInfo *ai_pwiWeapon1; - struct WeaponInfo *ai_pwiWeapon2; - INDEX ai_iAmmoAmmount; - INDEX ai_iMaxAmmoAmmount; - INDEX ai_iLastAmmoAmmount; - TIME ai_tmAmmoChanged; - BOOL ai_bHasWeapon; -}; - -// weapons' info structure -struct WeaponInfo { - enum WeaponType wi_wtWeapon; - CTextureObject *wi_ptoWeapon; - struct AmmoInfo *wi_paiAmmo; - BOOL wi_bHasWeapon; -}; - -extern struct WeaponInfo _awiWeapons[18]; -static struct AmmoInfo _aaiAmmo[8] = { - { &_toAShells, &_awiWeapons[4], &_awiWeapons[5], 0, 0, 0, -9, FALSE }, - { &_toABullets, &_awiWeapons[6], &_awiWeapons[7], 0, 0, 0, -9, FALSE }, - { &_toARockets, &_awiWeapons[8], NULL, 0, 0, 0, -9, FALSE }, - { &_toAGrenades, &_awiWeapons[9], &_awiWeapons[10], 0, 0, 0, -9, FALSE }, - { &_toANapalm, &_awiWeapons[12], NULL, 0, 0, 0, -9, FALSE }, - { &_toAElectricity, &_awiWeapons[14], &_awiWeapons[15], 0, 0, 0, -9, FALSE }, - { &_toAIronBall, &_awiWeapons[16], NULL, 0, 0, 0, -9, FALSE }, - { &_toAIronBall, &_awiWeapons[17], NULL, 0, 0, 0, -9, FALSE }, -}; - -struct WeaponInfo _awiWeapons[18] = { - { WEAPON_NONE, NULL, NULL, FALSE }, // 0 - { WEAPON_KNIFE, &_toWKnife, NULL, FALSE }, // 1 - { WEAPON_COLT, &_toWColt, NULL, FALSE }, // 2 - { WEAPON_DOUBLECOLT, &_toWColt, NULL, FALSE }, // 3 - { WEAPON_SINGLESHOTGUN, &_toWSingleShotgun, &_aaiAmmo[0], FALSE }, // 4 - { WEAPON_DOUBLESHOTGUN, &_toWDoubleShotgun, &_aaiAmmo[0], FALSE }, // 5 - { WEAPON_TOMMYGUN, &_toWTommygun, &_aaiAmmo[1], FALSE }, // 6 - { WEAPON_MINIGUN, &_toWMinigun, &_aaiAmmo[1], FALSE }, // 7 - { WEAPON_ROCKETLAUNCHER, &_toWRocketLauncher, &_aaiAmmo[2], FALSE }, // 8 - { WEAPON_GRENADELAUNCHER, &_toWGrenadeLauncher, &_aaiAmmo[3], FALSE }, // 9 - { WEAPON_NONE, NULL, NULL, FALSE }, //{ WEAPON_PIPEBOMB, &_toWPipeBomb, &_aaiAmmo[3], FALSE }, // 10 - { WEAPON_NONE, NULL, NULL, FALSE }, // 11 - { WEAPON_NONE, NULL, NULL, FALSE }, //{ WEAPON_FLAMER, &_toWFlamer, &_aaiAmmo[4], FALSE }, // 12 - { WEAPON_NONE, NULL, NULL, FALSE }, // 13 - { WEAPON_LASER, &_toWLaser, &_aaiAmmo[5], FALSE }, // 14 - { WEAPON_NONE, NULL, NULL, FALSE }, //{ WEAPON_GHOSTBUSTER, &_toWGhostBuster, &_aaiAmmo[5], FALSE }, // 15 - { WEAPON_IRONCANNON, &_toWIronCannon, &_aaiAmmo[6], FALSE }, // 16 - { WEAPON_NONE, NULL, NULL, FALSE }, //{ WEAPON_NUKECANNON, &_toWNukeCannon, &_aaiAmmo[7], FALSE }, // 17 -}; - - -// compare functions for qsort() -static int qsort_CompareNames( const void *ppPEN0, const void *ppPEN1) { - CPlayer &en0 = **(CPlayer**)ppPEN0; - CPlayer &en1 = **(CPlayer**)ppPEN1; - CTString strName0 = en0.GetPlayerName(); - CTString strName1 = en1.GetPlayerName(); - return strnicmp( strName0, strName1, 8); -} - -static int qsort_CompareScores( const void *ppPEN0, const void *ppPEN1) { - CPlayer &en0 = **(CPlayer**)ppPEN0; - CPlayer &en1 = **(CPlayer**)ppPEN1; - SLONG sl0 = en0.m_psGameStats.ps_iScore; - SLONG sl1 = en1.m_psGameStats.ps_iScore; - if( sl0sl1) return -1; - else return 0; -} - -static int qsort_CompareHealth( const void *ppPEN0, const void *ppPEN1) { - CPlayer &en0 = **(CPlayer**)ppPEN0; - CPlayer &en1 = **(CPlayer**)ppPEN1; - SLONG sl0 = (SLONG)ceil(en0.GetHealth()); - SLONG sl1 = (SLONG)ceil(en1.GetHealth()); - if( sl0sl1) return -1; - else return 0; -} - -static int qsort_CompareManas( const void *ppPEN0, const void *ppPEN1) { - CPlayer &en0 = **(CPlayer**)ppPEN0; - CPlayer &en1 = **(CPlayer**)ppPEN1; - SLONG sl0 = en0.m_iMana; - SLONG sl1 = en1.m_iMana; - if( sl0sl1) return -1; - else return 0; -} - -static int qsort_CompareFrags( const void *ppPEN0, const void *ppPEN1) { - CPlayer &en0 = **(CPlayer**)ppPEN0; - CPlayer &en1 = **(CPlayer**)ppPEN1; - SLONG sl0 = en0.m_psGameStats.ps_iKills; - SLONG sl1 = en1.m_psGameStats.ps_iKills; - if( sl0sl1) return -1; - else return 0; -} - -static int qsort_CompareDeaths( const void *ppPEN0, const void *ppPEN1) { - CPlayer &en0 = **(CPlayer**)ppPEN0; - CPlayer &en1 = **(CPlayer**)ppPEN1; - SLONG sl0 = en0.m_psGameStats.ps_iDeaths; - SLONG sl1 = en1.m_psGameStats.ps_iDeaths; - if( sl0sl1) return -1; - else return 0; -} - -#if 0 // DG: unused -static int qsort_CompareLatencies( const void *ppPEN0, const void *ppPEN1) { - CPlayer &en0 = **(CPlayer**)ppPEN0; - CPlayer &en1 = **(CPlayer**)ppPEN1; - SLONG sl0 = (SLONG)ceil(en0.m_tmLatency); - SLONG sl1 = (SLONG)ceil(en1.m_tmLatency); - if( sl0sl1) return -1; - else return 0; -} -#endif // 0 (unused) - -// prepare color transitions -static void PrepareColorTransitions( COLOR colFine, COLOR colHigh, COLOR colMedium, COLOR colLow, - FLOAT fMediumHigh, FLOAT fLowMedium, BOOL bSmooth) -{ - _cttHUD.ctt_colFine = colFine; - _cttHUD.ctt_colHigh = colHigh; - _cttHUD.ctt_colMedium = colMedium; - _cttHUD.ctt_colLow = colLow; - _cttHUD.ctt_fMediumHigh = fMediumHigh; - _cttHUD.ctt_fLowMedium = fLowMedium; - _cttHUD.ctt_bSmooth = bSmooth; -} - - - -// calculates shake ammount and color value depanding on value change -#define SHAKE_TIME (2.0f) -static COLOR AddShaker( PIX const pixAmmount, INDEX const iCurrentValue, INDEX &iLastValue, - TIME &tmChanged, FLOAT &fMoverX, FLOAT &fMoverY) -{ - // update shaking if needed - fMoverX = fMoverY = 0.0f; - const TIME tmNow = _pTimer->GetLerpedCurrentTick(); - if( iCurrentValue != iLastValue) { - iLastValue = iCurrentValue; - tmChanged = tmNow; - } else { - // in case of loading (timer got reseted) - tmChanged = ClampUp( tmChanged, tmNow); - } - - // no shaker? - const TIME tmDelta = tmNow - tmChanged; - if( tmDelta > SHAKE_TIME) return NONE; - ASSERT( tmDelta>=0); - // shake, baby shake! - const FLOAT fAmmount = _fResolutionScaling * _fCustomScaling * pixAmmount; - const FLOAT fMultiplier = (SHAKE_TIME-tmDelta)/SHAKE_TIME *fAmmount; - const INDEX iRandomizer = (INDEX)(tmNow*511.0f)*fAmmount*iCurrentValue; - const FLOAT fNormRnd1 = (FLOAT)((iRandomizer ^ (iRandomizer>>9)) & 1023) * 0.0009775f; // 1/1023 - normalized - const FLOAT fNormRnd2 = (FLOAT)((iRandomizer ^ (iRandomizer>>7)) & 1023) * 0.0009775f; // 1/1023 - normalized - fMoverX = (fNormRnd1 -0.5f) * fMultiplier; - fMoverY = (fNormRnd2 -0.5f) * fMultiplier; - // clamp to adjusted ammount (pixels relative to resolution and HUD scale - fMoverX = Clamp( fMoverX, -fAmmount, fAmmount); - fMoverY = Clamp( fMoverY, -fAmmount, fAmmount); - if( tmDelta < SHAKE_TIME/3) return C_WHITE; - else return NONE; -//return FloatToInt(tmDelta*4) & 1 ? C_WHITE : NONE; -} - - -// get current color from local color transitions table -static COLOR GetCurrentColor( FLOAT fNormalizedValue) -{ - // if value is in 'low' zone just return plain 'low' alert color - if( fNormalizedValue < _cttHUD.ctt_fLowMedium) return( _cttHUD.ctt_colLow & 0xFFFFFF00); - // if value is in out of 'extreme' zone just return 'extreme' color - if( fNormalizedValue > 1.0f) return( _cttHUD.ctt_colFine & 0xFFFFFF00); - - COLOR col; - // should blend colors? - if( _cttHUD.ctt_bSmooth) - { // lets do some interpolations - FLOAT fd, f1, f2; - COLOR col1, col2; - UBYTE ubH,ubS,ubV, ubH2,ubS2,ubV2; - // determine two colors for interpolation - if( fNormalizedValue > _cttHUD.ctt_fMediumHigh) { - f1 = 1.0f; - f2 = _cttHUD.ctt_fMediumHigh; - col1 = _cttHUD.ctt_colHigh; - col2 = _cttHUD.ctt_colMedium; - } else { // fNormalizedValue > _cttHUD.ctt_fLowMedium == TRUE ! - f1 = _cttHUD.ctt_fMediumHigh; - f2 = _cttHUD.ctt_fLowMedium; - col1 = _cttHUD.ctt_colMedium; - col2 = _cttHUD.ctt_colLow; - } - // determine interpolation strength - fd = (fNormalizedValue-f2) / (f1-f2); - // convert colors to HSV - ColorToHSV( col1, ubH, ubS, ubV); - ColorToHSV( col2, ubH2, ubS2, ubV2); - // interpolate H, S and V components - ubH = (UBYTE)(ubH*fd + ubH2*(1.0f-fd)); - ubS = (UBYTE)(ubS*fd + ubS2*(1.0f-fd)); - ubV = (UBYTE)(ubV*fd + ubV2*(1.0f-fd)); - // convert HSV back to COLOR - col = HSVToColor( ubH, ubS, ubV); - } - else - { // simple color picker - col = _cttHUD.ctt_colMedium; - if( fNormalizedValue > _cttHUD.ctt_fMediumHigh) col = _cttHUD.ctt_colHigh; - } - // all done - return( col & 0xFFFFFF00); -} - - - -// fill array with players' statistics (returns current number of players in game) -extern INDEX SetAllPlayersStats( INDEX iSortKey) -{ - // determine maximum number of players for this session - INDEX iPlayers = 0; - INDEX iMaxPlayers = _penPlayer->GetMaxPlayers(); - CPlayer *penCurrent; - // loop thru potentional players - for( INDEX i=0; iGetPlayerEntity(i); - if( penCurrent==NULL) continue; - // fill in player parameters - _apenPlayers[iPlayers] = penCurrent; - // advance to next real player - iPlayers++; - } - // sort statistics by some key if needed - switch( iSortKey) { - case PSK_NAME: qsort( _apenPlayers, iPlayers, sizeof(CPlayer*), qsort_CompareNames); break; - case PSK_SCORE: qsort( _apenPlayers, iPlayers, sizeof(CPlayer*), qsort_CompareScores); break; - case PSK_HEALTH: qsort( _apenPlayers, iPlayers, sizeof(CPlayer*), qsort_CompareHealth); break; - case PSK_MANA: qsort( _apenPlayers, iPlayers, sizeof(CPlayer*), qsort_CompareManas); break; - case PSK_FRAGS: qsort( _apenPlayers, iPlayers, sizeof(CPlayer*), qsort_CompareFrags); break; - case PSK_DEATHS: qsort( _apenPlayers, iPlayers, sizeof(CPlayer*), qsort_CompareDeaths); break; - default: break; // invalid or NONE key specified so do nothing - } - // all done - return iPlayers; -} - - - -// ----------------------- drawing functions - -// draw border with filter -static void HUD_DrawBorder( FLOAT fCenterX, FLOAT fCenterY, FLOAT fSizeX, FLOAT fSizeY, COLOR colTiles) -{ - // determine location - const FLOAT fCenterI = fCenterX*_pixDPWidth / 640.0f; - const FLOAT fCenterJ = fCenterY*_pixDPHeight / (480.0f * _pDP->dp_fWideAdjustment); - const FLOAT fSizeI = _fResolutionScaling*fSizeX; - const FLOAT fSizeJ = _fResolutionScaling*fSizeY; - const FLOAT fTileSize = 8*_fResolutionScaling*_fCustomScaling; - // determine exact positions - const FLOAT fLeft = fCenterI - fSizeI/2 -1; - const FLOAT fRight = fCenterI + fSizeI/2 +1; - const FLOAT fUp = fCenterJ - fSizeJ/2 -1; - const FLOAT fDown = fCenterJ + fSizeJ/2 +1; - const FLOAT fLeftEnd = fLeft + fTileSize; - const FLOAT fRightBeg = fRight - fTileSize; - const FLOAT fUpEnd = fUp + fTileSize; - const FLOAT fDownBeg = fDown - fTileSize; - // prepare texture - colTiles |= _ulAlphaHUD; - // put corners - _pDP->InitTexture( &_toTile, TRUE); // clamping on! - _pDP->AddTexture( fLeft, fUp, fLeftEnd, fUpEnd, colTiles); - _pDP->AddTexture( fRight,fUp, fRightBeg,fUpEnd, colTiles); - _pDP->AddTexture( fRight,fDown, fRightBeg,fDownBeg, colTiles); - _pDP->AddTexture( fLeft, fDown, fLeftEnd, fDownBeg, colTiles); - // put edges - _pDP->AddTexture( fLeftEnd,fUp, fRightBeg,fUpEnd, 0.4f,0.0f, 0.6f,1.0f, colTiles); - _pDP->AddTexture( fLeftEnd,fDown, fRightBeg,fDownBeg, 0.4f,0.0f, 0.6f,1.0f, colTiles); - _pDP->AddTexture( fLeft, fUpEnd, fLeftEnd, fDownBeg, 0.0f,0.4f, 1.0f,0.6f, colTiles); - _pDP->AddTexture( fRight, fUpEnd, fRightBeg,fDownBeg, 0.0f,0.4f, 1.0f,0.6f, colTiles); - // put center - _pDP->AddTexture( fLeftEnd, fUpEnd, fRightBeg, fDownBeg, 0.4f,0.4f, 0.6f,0.6f, colTiles); - _pDP->FlushRenderingQueue(); -} - - -// draw icon texture (if color = NONE, use colortransitions structure) -static void HUD_DrawIcon( FLOAT fCenterX, FLOAT fCenterY, CTextureObject &toIcon, - COLOR colDefault, FLOAT fNormValue, BOOL bBlink) -{ - // determine color - COLOR col = colDefault; - if( col==NONE) col = GetCurrentColor( fNormValue); - // determine blinking state - if( bBlink && fNormValue<=(_cttHUD.ctt_fLowMedium/2)) { - // activate blinking only if value is <= half the low edge - INDEX iCurrentTime = (INDEX)(_tmNow*4); - if( iCurrentTime&1) col = C_vdGRAY; - } - // determine location - const FLOAT fCenterI = fCenterX*_pixDPWidth / 640.0f; - const FLOAT fCenterJ = fCenterY*_pixDPHeight / (480.0f * _pDP->dp_fWideAdjustment); - // determine dimensions - CTextureData *ptd = (CTextureData*)toIcon.GetData(); - const FLOAT fHalfSizeI = _fResolutionScaling*_fCustomScaling * ptd->GetPixWidth() *0.5f; - const FLOAT fHalfSizeJ = _fResolutionScaling*_fCustomScaling * ptd->GetPixHeight() *0.5f; - // done - _pDP->InitTexture( &toIcon); - _pDP->AddTexture( fCenterI-fHalfSizeI, fCenterJ-fHalfSizeJ, - fCenterI+fHalfSizeI, fCenterJ+fHalfSizeJ, col|_ulAlphaHUD); - _pDP->FlushRenderingQueue(); -} - - -// draw text (or numbers, whatever) -static void HUD_DrawText( FLOAT fCenterX, FLOAT fCenterY, const CTString &strText, - COLOR colDefault, FLOAT fNormValue) -{ - // determine color - COLOR col = colDefault; - if( col==NONE) col = GetCurrentColor( fNormValue); - // determine location - PIX pixCenterI = (PIX)(fCenterX*_pixDPWidth / 640.0f); - PIX pixCenterJ = (PIX)(fCenterY*_pixDPHeight / (480.0f * _pDP->dp_fWideAdjustment)); - // done - _pDP->SetTextScaling( _fResolutionScaling*_fCustomScaling); - _pDP->PutTextCXY( strText, pixCenterI, pixCenterJ, col|_ulAlphaHUD); -} - - -// draw bar -static void HUD_DrawBar( FLOAT fCenterX, FLOAT fCenterY, PIX pixSizeX, PIX pixSizeY, - enum BarOrientations eBarOrientation, COLOR colDefault, FLOAT fNormValue) -{ - // determine color - COLOR col = colDefault; - if( col==NONE) col = GetCurrentColor( fNormValue); - // determine location and size - PIX pixCenterI = (PIX)(fCenterX*_pixDPWidth / 640.0f); - PIX pixCenterJ = (PIX)(fCenterY*_pixDPHeight / (480.0f * _pDP->dp_fWideAdjustment)); - PIX pixSizeI = (PIX)(_fResolutionScaling*pixSizeX); - PIX pixSizeJ = (PIX)(_fResolutionScaling*pixSizeY); - // fill bar background area - PIX pixLeft = pixCenterI-pixSizeI/2; - PIX pixUpper = pixCenterJ-pixSizeJ/2; - // determine bar position and inner size - switch( eBarOrientation) { - case BO_UP: - pixSizeJ *= fNormValue; - break; - case BO_DOWN: - pixUpper = pixUpper + (PIX)ceil(pixSizeJ * (1.0f-fNormValue)); - pixSizeJ *= fNormValue; - break; - case BO_LEFT: - pixSizeI *= fNormValue; - break; - case BO_RIGHT: - pixLeft = pixLeft + (PIX)ceil(pixSizeI * (1.0f-fNormValue)); - pixSizeI *= fNormValue; - break; - } - // done - _pDP->Fill( pixLeft, pixUpper, pixSizeI, pixSizeJ, col|_ulAlphaHUD); -} - - -// helper functions - -// fill weapon and ammo table with current state -static void FillWeaponAmmoTables(void) -{ - // ammo quantities - _aaiAmmo[0].ai_iAmmoAmmount = _penWeapons->m_iShells; - _aaiAmmo[0].ai_iMaxAmmoAmmount = _penWeapons->m_iMaxShells; - _aaiAmmo[1].ai_iAmmoAmmount = _penWeapons->m_iBullets; - _aaiAmmo[1].ai_iMaxAmmoAmmount = _penWeapons->m_iMaxBullets; - _aaiAmmo[2].ai_iAmmoAmmount = _penWeapons->m_iRockets; - _aaiAmmo[2].ai_iMaxAmmoAmmount = _penWeapons->m_iMaxRockets; - _aaiAmmo[3].ai_iAmmoAmmount = _penWeapons->m_iGrenades; - _aaiAmmo[3].ai_iMaxAmmoAmmount = _penWeapons->m_iMaxGrenades; - _aaiAmmo[4].ai_iAmmoAmmount = 0;//_penWeapons->m_iNapalm; - _aaiAmmo[4].ai_iMaxAmmoAmmount = 0;//_penWeapons->m_iMaxNapalm; - _aaiAmmo[5].ai_iAmmoAmmount = _penWeapons->m_iElectricity; - _aaiAmmo[5].ai_iMaxAmmoAmmount = _penWeapons->m_iMaxElectricity; - _aaiAmmo[6].ai_iAmmoAmmount = _penWeapons->m_iIronBalls; - _aaiAmmo[6].ai_iMaxAmmoAmmount = _penWeapons->m_iMaxIronBalls; - _aaiAmmo[7].ai_iAmmoAmmount = 0;//_penWeapons->m_iNukeBalls; - _aaiAmmo[7].ai_iMaxAmmoAmmount = 0;//_penWeapons->m_iMaxNukeBalls; - - // prepare ammo table for weapon possesion - INDEX i, iAvailableWeapons = _penWeapons->m_iAvailableWeapons; - for( i=0; i<8; i++) _aaiAmmo[i].ai_bHasWeapon = FALSE; - // weapon possesion - for( i=WEAPON_NONE+1; iai_bHasWeapon |= _awiWeapons[i].wi_bHasWeapon; - } - } -} - - - -// main - -// render interface (frontend) to drawport -// (units are in pixels for 640x480 resolution - for other res HUD will be scalled automatically) -extern void DrawHUD( const CPlayer *penPlayerCurrent, CDrawPort *pdpCurrent, BOOL bSnooping) -{ - // no player - no info, sorry - if( penPlayerCurrent==NULL || (penPlayerCurrent->GetFlags()&ENF_DELETED)) return; - - // find last values in case of predictor - CPlayer *penLast = (CPlayer*)penPlayerCurrent; - if( penPlayerCurrent->IsPredictor()) penLast = (CPlayer*)(((CPlayer*)penPlayerCurrent)->GetPredicted()); - ASSERT( penLast!=NULL); - if( penLast==NULL) return; // !!!! just in case - - // cache local variables - hud_fOpacity = Clamp( hud_fOpacity, 0.1f, 1.0f); - hud_fScaling = Clamp( hud_fScaling, 0.5f, 1.2f); - _penPlayer = penPlayerCurrent; - _penWeapons = (CPlayerWeapons*)&*_penPlayer->m_penWeapons; - _pDP = pdpCurrent; - _pixDPWidth = _pDP->GetWidth(); - _pixDPHeight = _pDP->GetHeight(); - _fCustomScaling = hud_fScaling; - _fResolutionScaling = (FLOAT)_pixDPWidth /640.0f; - _colHUD = C_GREEN; - _ulAlphaHUD = NormFloatToByte(hud_fOpacity); - _tmNow = _pTimer->CurrentTick(); - - // set HUD colorization; - COLOR colMax = _colHUD; - COLOR colTop = _colHUD; - COLOR colMid = _colHUD; - - // adjust borders color in case of spying mode - COLOR colBorder = _colHUD; - if( bSnooping) { - UBYTE ubR,ubG,ubB; - ColorToRGB( colBorder, ubR,ubG,ubB); - colBorder = RGBToColor( ubG,ubB,ubR); // shift and xor color components - if( ((ULONG)(_tmNow*5))&1) { - colBorder = (colBorder>>1) & 0x7F7F7F00; // darken flash and scale - _fCustomScaling *= 0.933f; - } - } - - // prepare font and text dimensions - CTString strValue; - PIX pixCharWidth; - FLOAT fValue, fNormValue, fCol, fRow; - _pDP->SetFont( &_fdNumbersFont); - pixCharWidth = _fdNumbersFont.GetWidth() + _fdNumbersFont.GetCharSpacing() +1; - FLOAT fChrUnit = pixCharWidth * _fCustomScaling; - - const PIX pixTopBound = 6; - const PIX pixLeftBound = 6; - const PIX pixBottomBound = (480 * _pDP->dp_fWideAdjustment) -pixTopBound; - const PIX pixRightBound = 640-pixLeftBound; - FLOAT fOneUnit = (32+0) * _fCustomScaling; // unit size - FLOAT fAdvUnit = (32+4) * _fCustomScaling; // unit advancer - FLOAT fNextUnit = (32+8) * _fCustomScaling; // unit advancer - FLOAT fHalfUnit = fOneUnit * 0.5f; - FLOAT fMoverX, fMoverY; - COLOR colDefault; - - // prepare and draw health info - fValue = ClampDn( _penPlayer->GetHealth(), 0.0f); // never show negative health - fNormValue = fValue/TOP_HEALTH; - strValue.PrintF( "%d", (SLONG)ceil(fValue)); - PrepareColorTransitions( colMax, colTop, colMid, C_RED, 0.5f, 0.25f, FALSE); - fRow = pixBottomBound-fHalfUnit; - fCol = pixLeftBound+fHalfUnit; - colDefault = AddShaker( 5, fValue, penLast->m_iLastHealth, penLast->m_tmHealthChanged, fMoverX, fMoverY); - HUD_DrawBorder( fCol+fMoverX, fRow+fMoverY, fOneUnit, fOneUnit, colBorder); - fCol += fAdvUnit+fChrUnit*3/2 -fHalfUnit; - HUD_DrawBorder( fCol, fRow, fChrUnit*3, fOneUnit, colBorder); - HUD_DrawText( fCol, fRow, strValue, colDefault, fNormValue); - fCol -= fAdvUnit+fChrUnit*3/2 -fHalfUnit; - HUD_DrawIcon( fCol+fMoverX, fRow+fMoverY, _toHealth, _colHUD, fNormValue, TRUE); - - // prepare and draw armor info (eventually) - fValue = _penPlayer->m_fArmor; - if( fValue > 0.0f) { - fNormValue = fValue/TOP_ARMOR; - strValue.PrintF( "%d", (SLONG)ceil(fValue)); - PrepareColorTransitions( colMax, colTop, colMid, C_lGRAY, 0.5f, 0.25f, FALSE); - fRow = pixBottomBound- (fNextUnit+fHalfUnit);//*_pDP->dp_fWideAdjustment; - fCol = pixLeftBound+ fHalfUnit; - colDefault = AddShaker( 3, fValue, penLast->m_iLastArmor, penLast->m_tmArmorChanged, fMoverX, fMoverY); - HUD_DrawBorder( fCol+fMoverX, fRow+fMoverY, fOneUnit, fOneUnit, colBorder); - fCol += fAdvUnit+fChrUnit*3/2 -fHalfUnit; - HUD_DrawBorder( fCol, fRow, fChrUnit*3, fOneUnit, colBorder); - HUD_DrawText( fCol, fRow, strValue, NONE, fNormValue); - fCol -= fAdvUnit+fChrUnit*3/2 -fHalfUnit; - HUD_DrawIcon( fCol+fMoverX, fRow+fMoverY, _toArmor, _colHUD, fNormValue, FALSE); - } - - // prepare and draw ammo and weapon info - CTextureObject *ptoCurrentAmmo=NULL, *ptoCurrentWeapon=NULL, *ptoWantedWeapon=NULL; - INDEX iCurrentWeapon = _penWeapons->m_iCurrentWeapon; - INDEX iWantedWeapon = _penWeapons->m_iWantedWeapon; - // determine corresponding ammo and weapon texture component - ptoCurrentWeapon = _awiWeapons[iCurrentWeapon].wi_ptoWeapon; - ptoWantedWeapon = _awiWeapons[iWantedWeapon].wi_ptoWeapon; - - AmmoInfo *paiCurrent = _awiWeapons[iCurrentWeapon].wi_paiAmmo; - if( paiCurrent!=NULL) ptoCurrentAmmo = paiCurrent->ai_ptoAmmo; - - // draw complete weapon info if knife isn't current weapon - if( ptoCurrentAmmo!=NULL && !GetSP()->sp_bInfiniteAmmo) { - // determine ammo quantities - FLOAT fMaxValue = _penWeapons->GetMaxAmmo(); - fValue = _penWeapons->GetAmmo(); - fNormValue = fValue / fMaxValue; - strValue.PrintF( "%d", (SLONG)ceil(fValue)); - PrepareColorTransitions( colMax, colTop, colMid, C_RED, 0.5f, 0.25f, FALSE); - BOOL bDrawAmmoIcon = _fCustomScaling<=1.0f; - // draw ammo, value and weapon - fRow = pixBottomBound-fHalfUnit; - fCol = 175 + fHalfUnit; - colDefault = AddShaker( 4, fValue, penLast->m_iLastAmmo, penLast->m_tmAmmoChanged, fMoverX, fMoverY); - HUD_DrawBorder( fCol+fMoverX, fRow+fMoverY, fOneUnit, fOneUnit, colBorder); - fCol += fAdvUnit+fChrUnit*3/2 -fHalfUnit; - HUD_DrawBorder( fCol, fRow, fChrUnit*3, fOneUnit, colBorder); - if( bDrawAmmoIcon) { - fCol += fAdvUnit+fChrUnit*3/2 -fHalfUnit; - HUD_DrawBorder( fCol, fRow, fOneUnit, fOneUnit, colBorder); - HUD_DrawIcon( fCol, fRow, *ptoCurrentAmmo, _colHUD, fNormValue, TRUE); - fCol -= fAdvUnit+fChrUnit*3/2 -fHalfUnit; - } - HUD_DrawText( fCol, fRow, strValue, colDefault, fNormValue); - fCol -= fAdvUnit+fChrUnit*3/2 -fHalfUnit; - HUD_DrawIcon( fCol+fMoverX, fRow+fMoverY, *ptoCurrentWeapon, _colHUD, fNormValue, !bDrawAmmoIcon); - } else if( ptoCurrentWeapon!=NULL) { - // draw only knife or colt icons (ammo is irrelevant) - fRow = pixBottomBound-fHalfUnit; - fCol = 205 + fHalfUnit; - HUD_DrawBorder( fCol, fRow, fOneUnit, fOneUnit, colBorder); - HUD_DrawIcon( fCol, fRow, *ptoCurrentWeapon, _colHUD, fNormValue, FALSE); - } - - - // display all ammo infos - INDEX i; - FLOAT fAdv; - COLOR colIcon, colBar; - PrepareColorTransitions( colMax, colTop, colMid, C_RED, 0.5f, 0.25f, FALSE); - // reduce the size of icon slightly - _fCustomScaling = ClampDn( _fCustomScaling*0.8f, 0.5f); - const FLOAT fOneUnitS = fOneUnit *0.8f; - const FLOAT fAdvUnitS = fAdvUnit *0.8f; - //const FLOAT fNextUnitS = fNextUnit *0.8f; - const FLOAT fHalfUnitS = fHalfUnit *0.8f; - - // prepare postition and ammo quantities - fRow = pixBottomBound-fHalfUnitS; - fCol = pixRightBound -fHalfUnitS; - const FLOAT fBarPos = fHalfUnitS*0.7f; - FillWeaponAmmoTables(); - - // loop thru all ammo types - if (!GetSP()->sp_bInfiniteAmmo) { - for( i=7; i>=0; i--) { - // if no ammo and hasn't got that weapon - just skip this ammo - AmmoInfo &ai = _aaiAmmo[i]; - ASSERT( ai.ai_iAmmoAmmount>=0); - if( ai.ai_iAmmoAmmount==0 && !ai.ai_bHasWeapon) continue; - // display ammo info - colIcon = _colHUD; - if( ai.ai_iAmmoAmmount==0) colIcon = C_GRAY; - if( ptoCurrentAmmo == ai.ai_ptoAmmo) colIcon = C_WHITE; - fNormValue = (FLOAT)ai.ai_iAmmoAmmount / ai.ai_iMaxAmmoAmmount; - colBar = AddShaker( 4, ai.ai_iAmmoAmmount, ai.ai_iLastAmmoAmmount, ai.ai_tmAmmoChanged, fMoverX, fMoverY); - HUD_DrawBorder( fCol, fRow+fMoverY, fOneUnitS, fOneUnitS, colBorder); - HUD_DrawIcon( fCol, fRow+fMoverY, *_aaiAmmo[i].ai_ptoAmmo, colIcon, fNormValue, FALSE); - HUD_DrawBar( fCol+fBarPos, fRow+fMoverY, fOneUnitS/5, fOneUnitS-2, BO_DOWN, colBar, fNormValue); - // advance to next position - fCol -= fAdvUnitS; - } - } - - // if weapon change is in progress - _fCustomScaling = hud_fScaling; - hud_tmWeaponsOnScreen = Clamp( hud_tmWeaponsOnScreen, 0.0f, 10.0f); - if( (_tmNow - _penWeapons->m_tmWeaponChangeRequired) < hud_tmWeaponsOnScreen) { - // determine number of weapons that player has - INDEX ctWeapons = 0; - for( i=WEAPON_NONE+1; iai_iAmmoAmmount==0) colIcon = C_dGRAY; - if( ptoWantedWeapon == _awiWeapons[i].wi_ptoWeapon) colIcon = C_WHITE; - HUD_DrawBorder( fCol, fRow, fOneUnit, fOneUnit, colIcon); - HUD_DrawIcon( fCol, fRow, *_awiWeapons[i].wi_ptoWeapon, colIcon, 1.0f, FALSE); - // advance to next position - fCol += fAdvUnit; - } - } - - const FLOAT fUpperSize = ClampDn(_fCustomScaling*0.5f, 0.5f)/_fCustomScaling; - _fCustomScaling*=fUpperSize; - ASSERT( _fCustomScaling>=0.5f); - fChrUnit *= fUpperSize; - fOneUnit *= fUpperSize; - fHalfUnit *= fUpperSize; - fAdvUnit *= fUpperSize; - fNextUnit *= fUpperSize; - - // draw oxygen info if needed - BOOL bOxygenOnScreen = FALSE; - fValue = _penPlayer->en_tmMaxHoldBreath - (_pTimer->CurrentTick() - _penPlayer->en_tmLastBreathed); - if( _penPlayer->IsConnected() && (_penPlayer->GetFlags()&ENF_ALIVE) && fValue<30.0f) { - // prepare and draw oxygen info - fRow = pixTopBound + fOneUnit + fNextUnit; - fCol = 280.0f; - fAdv = fAdvUnit + fOneUnit*4/2 - fHalfUnit; - PrepareColorTransitions( colMax, colTop, colMid, C_RED, 0.5f, 0.25f, FALSE); - fNormValue = fValue/30.0f; - fNormValue = ClampDn(fNormValue, 0.0f); - HUD_DrawBorder( fCol, fRow, fOneUnit, fOneUnit, colBorder); - HUD_DrawBorder( fCol+fAdv, fRow, fOneUnit*4, fOneUnit, colBorder); - HUD_DrawBar( fCol+fAdv, fRow, fOneUnit*4*0.975, fOneUnit*0.9375, BO_LEFT, NONE, fNormValue); - HUD_DrawIcon( fCol, fRow, _toOxygen, _colHUD, fNormValue, TRUE); - bOxygenOnScreen = TRUE; - } - - // draw boss energy if needed - if( _penPlayer->m_penMainMusicHolder!=NULL) { - CMusicHolder &mh = (CMusicHolder&)*_penPlayer->m_penMainMusicHolder; - fNormValue = 0; - - if( mh.m_penBoss!=NULL && (mh.m_penBoss->en_ulFlags&ENF_ALIVE)) { - CEnemyBase &eb = (CEnemyBase&)*mh.m_penBoss; - ASSERT( eb.m_fMaxHealth>0); - fValue = eb.GetHealth(); - fNormValue = fValue/eb.m_fMaxHealth; - } - if( mh.m_penCounter!=NULL) { - CEnemyCounter &ec = (CEnemyCounter&)*mh.m_penCounter; - if (ec.m_iCount>0) { - fValue = ec.m_iCount; - fNormValue = fValue/ec.m_iCountFrom; - } - } - if (fNormValue>0) { - // prepare and draw boss energy info - PrepareColorTransitions( colMax, colTop, colMid, C_RED, 0.5f, 0.25f, FALSE); - fRow = pixTopBound + fOneUnit + fNextUnit; - fCol = 184.0f; - fAdv = fAdvUnit+ fOneUnit*16/2 -fHalfUnit; - if( bOxygenOnScreen) fRow += fNextUnit; - HUD_DrawBorder( fCol, fRow, fOneUnit, fOneUnit, colBorder); - HUD_DrawBorder( fCol+fAdv, fRow, fOneUnit*16, fOneUnit, colBorder); - HUD_DrawBar( fCol+fAdv, fRow, fOneUnit*16*0.995, fOneUnit*0.9375, BO_LEFT, NONE, fNormValue); - HUD_DrawIcon( fCol, fRow, _toHealth, _colHUD, fNormValue, FALSE); - } - } - - // determine scaling of normal text and play mode - const FLOAT fTextScale = (_fResolutionScaling+1) *0.5f; - const BOOL bSinglePlay = GetSP()->sp_bSinglePlayer; - const BOOL bCooperative = GetSP()->sp_bCooperative && !bSinglePlay; - const BOOL bScoreMatch = !GetSP()->sp_bCooperative && !GetSP()->sp_bUseFrags; - const BOOL bFragMatch = !GetSP()->sp_bCooperative && GetSP()->sp_bUseFrags; - COLOR colMana, colFrags, colDeaths, colHealth, colArmor; - COLOR colScore = _colHUD; - INDEX iScoreSum = 0; - - // if not in single player mode, we'll have to calc (and maybe printout) other players' info - if( !bSinglePlay) - { - // set font and prepare font parameters - _pfdDisplayFont->SetVariableWidth(); - _pDP->SetFont( _pfdDisplayFont); - _pDP->SetTextScaling( fTextScale); - FLOAT fCharHeight = (_pfdDisplayFont->GetHeight()-2)*fTextScale; - // generate and sort by mana list of active players - BOOL bMaxScore=TRUE, bMaxMana=TRUE, bMaxFrags=TRUE, bMaxDeaths=TRUE; - hud_iSortPlayers = Clamp( hud_iSortPlayers, -1, 6); - SortKeys eKey = (SortKeys)hud_iSortPlayers; - if (hud_iSortPlayers==-1) { - if (bCooperative) eKey = PSK_HEALTH; - else if (bScoreMatch) eKey = PSK_SCORE; - else if (bFragMatch) eKey = PSK_FRAGS; - else { ASSERT(FALSE); eKey = PSK_NAME; } - } - if( bCooperative) eKey = (SortKeys)Clamp( (INDEX)eKey, 0, 3); - if( eKey==PSK_HEALTH && (bScoreMatch || bFragMatch)) { eKey = PSK_NAME; }; // prevent health snooping in deathmatch - INDEX iPlayers = SetAllPlayersStats(eKey); - // loop thru players - for( INDEX i=0; iGetPlayerName(); - const INDEX iScore = penPlayer->m_psGameStats.ps_iScore; - const INDEX iMana = penPlayer->m_iMana; - const INDEX iFrags = penPlayer->m_psGameStats.ps_iKills; - const INDEX iDeaths = penPlayer->m_psGameStats.ps_iDeaths; - const INDEX iHealth = ClampDn( (INDEX)ceil( penPlayer->GetHealth()), 0); - const INDEX iArmor = ClampDn( (INDEX)ceil( penPlayer->m_fArmor), 0); - CTString strScore, strMana, strFrags, strDeaths, strHealth, strArmor; - strScore.PrintF( "%d", iScore); - strMana.PrintF( "%d", iMana); - strFrags.PrintF( "%d", iFrags); - strDeaths.PrintF( "%d", iDeaths); - strHealth.PrintF( "%d", iHealth); - strArmor.PrintF( "%d", iArmor); - // detemine corresponding colors - colHealth = C_mlRED; - colMana = colScore = colFrags = colDeaths = colArmor = C_lGRAY; - if( iMana > _penPlayer->m_iMana) { bMaxMana = FALSE; colMana = C_WHITE; } - if( iScore > _penPlayer->m_psGameStats.ps_iScore) { bMaxScore = FALSE; colScore = C_WHITE; } - if( iFrags > _penPlayer->m_psGameStats.ps_iKills) { bMaxFrags = FALSE; colFrags = C_WHITE; } - if( iDeaths > _penPlayer->m_psGameStats.ps_iDeaths) { bMaxDeaths = FALSE; colDeaths = C_WHITE; } - if( penPlayer==_penPlayer) colScore = colMana = colFrags = colDeaths = _colHUD; // current player - if( iHealth>25) colHealth = _colHUD; - if( iArmor >25) colArmor = _colHUD; - // eventually print it out - if( hud_iShowPlayers==1 || (hud_iShowPlayers==-1 && !bSinglePlay)) { - // printout location and info aren't the same for deathmatch and coop play - const FLOAT fCharWidth = (PIX)((_pfdDisplayFont->GetWidth()-2) *fTextScale); - if( bCooperative) { - _pDP->PutTextR( strName+":", _pixDPWidth-8*fCharWidth, fCharHeight*i+fOneUnit*2, colScore |_ulAlphaHUD); - _pDP->PutText( "/", _pixDPWidth-4*fCharWidth, fCharHeight*i+fOneUnit*2, _colHUD |_ulAlphaHUD); - _pDP->PutTextC( strHealth, _pixDPWidth-6*fCharWidth, fCharHeight*i+fOneUnit*2, colHealth|_ulAlphaHUD); - _pDP->PutTextC( strArmor, _pixDPWidth-2*fCharWidth, fCharHeight*i+fOneUnit*2, colArmor |_ulAlphaHUD); - } else if( bScoreMatch) { - _pDP->PutTextR( strName+":", _pixDPWidth-12*fCharWidth, fCharHeight*i+fOneUnit*2, _colHUD |_ulAlphaHUD); - _pDP->PutText( "/", _pixDPWidth- 5*fCharWidth, fCharHeight*i+fOneUnit*2, _colHUD |_ulAlphaHUD); - _pDP->PutTextC( strScore, _pixDPWidth- 8*fCharWidth, fCharHeight*i+fOneUnit*2, colScore|_ulAlphaHUD); - _pDP->PutTextC( strMana, _pixDPWidth- 2*fCharWidth, fCharHeight*i+fOneUnit*2, colMana |_ulAlphaHUD); - } else { // fragmatch! - _pDP->PutTextR( strName+":", _pixDPWidth-8*fCharWidth, fCharHeight*i+fOneUnit*2, _colHUD |_ulAlphaHUD); - _pDP->PutText( "/", _pixDPWidth-4*fCharWidth, fCharHeight*i+fOneUnit*2, _colHUD |_ulAlphaHUD); - _pDP->PutTextC( strFrags, _pixDPWidth-6*fCharWidth, fCharHeight*i+fOneUnit*2, colFrags |_ulAlphaHUD); - _pDP->PutTextC( strDeaths, _pixDPWidth-2*fCharWidth, fCharHeight*i+fOneUnit*2, colDeaths|_ulAlphaHUD); - } - } - // calculate summ of scores (for coop mode) - iScoreSum += iScore; - } - - // prepare color for local player printouts - bMaxScore ? colScore = C_WHITE : colScore = C_lGRAY; - bMaxMana ? colMana = C_WHITE : colMana = C_lGRAY; - bMaxFrags ? colFrags = C_WHITE : colFrags = C_lGRAY; - bMaxDeaths ? colDeaths = C_WHITE : colDeaths = C_lGRAY; - } - - // printout player latency if needed - if( hud_bShowLatency) { - CTString strLatency; - strLatency.PrintF( "%4.0fms", _penPlayer->m_tmLatency*1000.0f); - PIX pixFontHeight = (PIX)(_pfdDisplayFont->GetHeight() *fTextScale +fTextScale+1); - _pfdDisplayFont->SetFixedWidth(); - _pDP->SetFont( _pfdDisplayFont); - _pDP->SetTextScaling( fTextScale); - _pDP->SetTextCharSpacing( -2.0f*fTextScale); - _pDP->PutTextR( strLatency, _pixDPWidth, _pixDPHeight-pixFontHeight, C_WHITE|CT_OPAQUE); - } - // restore font defaults - _pfdDisplayFont->SetVariableWidth(); - _pDP->SetFont( &_fdNumbersFont); - _pDP->SetTextCharSpacing(1); - - // prepare output strings and formats depending on game type - FLOAT fWidthAdj = 8; - INDEX iScore = _penPlayer->m_psGameStats.ps_iScore; - INDEX iMana = _penPlayer->m_iMana; - if( bFragMatch) { - fWidthAdj = 4; - iScore = _penPlayer->m_psGameStats.ps_iKills; - iMana = _penPlayer->m_psGameStats.ps_iDeaths; - } else if( bCooperative) { - // in case of coop play, show squad (common) score - iScore = iScoreSum; - } - - // prepare and draw score or frags info - strValue.PrintF( "%d", iScore); - fRow = pixTopBound +fHalfUnit; - fCol = pixLeftBound +fHalfUnit; - fAdv = fAdvUnit+ fChrUnit*fWidthAdj/2 -fHalfUnit; - HUD_DrawBorder( fCol, fRow, fOneUnit, fOneUnit, colBorder); - HUD_DrawBorder( fCol+fAdv, fRow, fChrUnit*fWidthAdj, fOneUnit, colBorder); - HUD_DrawText( fCol+fAdv, fRow, strValue, colScore, 1.0f); - HUD_DrawIcon( fCol, fRow, _toFrags, colScore, 1.0f, FALSE); - - // eventually draw mana info - if( bScoreMatch || bFragMatch) { - strValue.PrintF( "%d", iMana); - fRow = pixTopBound + fNextUnit+fHalfUnit; - fCol = pixLeftBound + fHalfUnit; - fAdv = fAdvUnit+ fChrUnit*fWidthAdj/2 -fHalfUnit; - HUD_DrawBorder( fCol, fRow, fOneUnit, fOneUnit, colBorder); - HUD_DrawBorder( fCol+fAdv, fRow, fChrUnit*fWidthAdj, fOneUnit, colBorder); - HUD_DrawText( fCol+fAdv, fRow, strValue, colMana, 1.0f); - HUD_DrawIcon( fCol, fRow, _toDeaths, colMana, 1.0f, FALSE); - } - - // if single player or cooperative mode - if( bSinglePlay || bCooperative) - { - // prepare and draw hiscore info - strValue.PrintF( "%d", Max(_penPlayer->m_iHighScore, _penPlayer->m_psGameStats.ps_iScore)); - BOOL bBeating = _penPlayer->m_psGameStats.ps_iScore>_penPlayer->m_iHighScore; - fRow = pixTopBound+fHalfUnit; - fCol = 320.0f-fOneUnit-fChrUnit*8/2; - fAdv = fAdvUnit+ fChrUnit*8/2 -fHalfUnit; - HUD_DrawBorder( fCol, fRow, fOneUnit, fOneUnit, colBorder); - HUD_DrawBorder( fCol+fAdv, fRow, fChrUnit*8, fOneUnit, colBorder); - HUD_DrawText( fCol+fAdv, fRow, strValue, NONE, bBeating ? 0.0f : 1.0f); - HUD_DrawIcon( fCol, fRow, _toHiScore, _colHUD, 1.0f, FALSE); - - // prepare and draw unread messages - if( hud_bShowMessages && _penPlayer->m_ctUnreadMessages>0) { - strValue.PrintF( "%d", _penPlayer->m_ctUnreadMessages); - fRow = pixTopBound+fHalfUnit; - fCol = pixRightBound-fHalfUnit-fAdvUnit-fChrUnit*4; - const FLOAT tmIn = 0.5f; - const FLOAT tmOut = 0.5f; - const FLOAT tmStay = 2.0f; - FLOAT tmDelta = _pTimer->GetLerpedCurrentTick()-_penPlayer->m_tmAnimateInbox; - COLOR col = _colHUD; - if (tmDelta>0 && tmDelta<(tmIn+tmStay+tmOut) && bSinglePlay) { - FLOAT fRatio = 0.0f; - if (tmDeltatmIn+tmStay) { - fRatio = (tmIn+tmStay+tmOut-tmDelta)/tmOut; - } else { - fRatio = 1.0f; - } - fRow+=fAdvUnit*5*fRatio; - fCol-=fAdvUnit*15*fRatio; - col = LerpColor(_colHUD, C_WHITE|0xFF, fRatio); - } - fAdv = fAdvUnit+ fChrUnit*4/2 -fHalfUnit; - HUD_DrawBorder( fCol, fRow, fOneUnit, fOneUnit, col); - HUD_DrawBorder( fCol+fAdv, fRow, fChrUnit*4, fOneUnit, col); - HUD_DrawText( fCol+fAdv, fRow, strValue, col, 1.0f); - HUD_DrawIcon( fCol, fRow, _toMessage, col, 0.0f, TRUE); - } - } - - // draw cheat modes - if( GetSP()->sp_ctMaxPlayers==1) { - INDEX iLine=1; - ULONG ulAlpha = sin(_tmNow*16)*96 +128; - PIX pixFontHeight = _pfdConsoleFont->fd_pixCharHeight; - const COLOR colCheat = _colHUD; - _pDP->SetFont( _pfdConsoleFont); - _pDP->SetTextScaling( 1.0f); - const FLOAT fchtTM = cht_fTranslationMultiplier; // for text formatting sake :) - if( fchtTM > 1.0f) { _pDP->PutTextR( "turbo", _pixDPWidth-1, _pixDPHeight-pixFontHeight*iLine, colCheat|ulAlpha); iLine++; } - if( cht_bInvisible) { _pDP->PutTextR( "invisible", _pixDPWidth-1, _pixDPHeight-pixFontHeight*iLine, colCheat|ulAlpha); iLine++; } - if( cht_bGhost) { _pDP->PutTextR( "ghost", _pixDPWidth-1, _pixDPHeight-pixFontHeight*iLine, colCheat|ulAlpha); iLine++; } - if( cht_bFly) { _pDP->PutTextR( "fly", _pixDPWidth-1, _pixDPHeight-pixFontHeight*iLine, colCheat|ulAlpha); iLine++; } - if( cht_bGod) { _pDP->PutTextR( "god", _pixDPWidth-1, _pixDPHeight-pixFontHeight*iLine, colCheat|ulAlpha); iLine++; } - } -} - - - -// initialized all whats need for drawing HUD -extern void InitHUD(void) -{ - // try to - try { - // initialize and load HUD numbers font - DECLARE_CTFILENAME( fnFont, "Fonts\\Numbers3.fnt"); - _fdNumbersFont.Load_t( fnFont); - //_fdNumbersFont.SetCharSpacing(0); - - // initialize status bar textures - _toHealth.SetData_t( CTFILENAME("Textures\\Interface\\HSuper.tex")); - _toArmor.SetData_t( CTFILENAME("Textures\\Interface\\ArStrong.tex")); - _toOxygen.SetData_t( CTFILENAME("Textures\\Interface\\Oxygen-2.tex")); - _toFrags.SetData_t( CTFILENAME("Textures\\Interface\\IBead.tex")); - _toDeaths.SetData_t( CTFILENAME("Textures\\Interface\\ISkull.tex")); - _toScore.SetData_t( CTFILENAME("Textures\\Interface\\IScore.tex")); - _toHiScore.SetData_t( CTFILENAME("Textures\\Interface\\IHiScore.tex")); - _toMessage.SetData_t( CTFILENAME("Textures\\Interface\\IMessage.tex")); - _toMana.SetData_t( CTFILENAME("Textures\\Interface\\IValue.tex")); - // initialize ammo textures - _toAShells.SetData_t( CTFILENAME("Textures\\Interface\\AmShells.tex")); - _toABullets.SetData_t( CTFILENAME("Textures\\Interface\\AmBullets.tex")); - _toARockets.SetData_t( CTFILENAME("Textures\\Interface\\AmRockets.tex")); - _toAGrenades.SetData_t( CTFILENAME("Textures\\Interface\\AmGrenades.tex")); - _toANapalm.SetData_t( CTFILENAME("Textures\\Interface\\AmFuelReservoir.tex")); - _toAElectricity.SetData_t( CTFILENAME("Textures\\Interface\\AmElectricity.tex")); - _toAIronBall.SetData_t( CTFILENAME("Textures\\Interface\\AmCannon.tex")); - // initialize weapon textures - _toWKnife.SetData_t( CTFILENAME("Textures\\Interface\\WKnife.tex")); - _toWColt.SetData_t( CTFILENAME("Textures\\Interface\\WColt.tex")); - _toWSingleShotgun.SetData_t( CTFILENAME("Textures\\Interface\\WSingleShotgun.tex")); - _toWDoubleShotgun.SetData_t( CTFILENAME("Textures\\Interface\\WDoubleShotgun.tex")); - _toWTommygun.SetData_t( CTFILENAME("Textures\\Interface\\WTommygun.tex")); - _toWMinigun.SetData_t( CTFILENAME("Textures\\Interface\\WMinigun.tex")); - _toWRocketLauncher.SetData_t( CTFILENAME("Textures\\Interface\\WRocketLauncher.tex")); - _toWGrenadeLauncher.SetData_t( CTFILENAME("Textures\\Interface\\WGrenadeLauncher.tex")); - _toWPipeBomb.SetData_t( CTFILENAME("Textures\\Interface\\WPipeBomb.tex")); - _toWFlamer.SetData_t( CTFILENAME("Textures\\Interface\\WFlamer.tex")); - _toWGhostBuster.SetData_t( CTFILENAME("Textures\\Interface\\WGhostBuster.tex")); - _toWLaser.SetData_t( CTFILENAME("Textures\\Interface\\WLaser.tex")); - _toWIronCannon.SetData_t( CTFILENAME("Textures\\Interface\\WCannon.tex")); - // initialize tile texture - _toTile.SetData_t( CTFILENAME("Textures\\Interface\\Tile.tex")); - - // set all textures as constant - ((CTextureData*)_toHealth .GetData())->Force(TEX_CONSTANT); - ((CTextureData*)_toArmor .GetData())->Force(TEX_CONSTANT); - ((CTextureData*)_toOxygen .GetData())->Force(TEX_CONSTANT); - ((CTextureData*)_toFrags .GetData())->Force(TEX_CONSTANT); - ((CTextureData*)_toDeaths .GetData())->Force(TEX_CONSTANT); - ((CTextureData*)_toScore .GetData())->Force(TEX_CONSTANT); - ((CTextureData*)_toHiScore.GetData())->Force(TEX_CONSTANT); - ((CTextureData*)_toMessage.GetData())->Force(TEX_CONSTANT); - ((CTextureData*)_toMana .GetData())->Force(TEX_CONSTANT); - ((CTextureData*)_toAShells .GetData())->Force(TEX_CONSTANT); - ((CTextureData*)_toABullets .GetData())->Force(TEX_CONSTANT); - ((CTextureData*)_toARockets .GetData())->Force(TEX_CONSTANT); - ((CTextureData*)_toAGrenades .GetData())->Force(TEX_CONSTANT); - ((CTextureData*)_toANapalm .GetData())->Force(TEX_CONSTANT); - ((CTextureData*)_toAElectricity.GetData())->Force(TEX_CONSTANT); - ((CTextureData*)_toAIronBall .GetData())->Force(TEX_CONSTANT); - ((CTextureData*)_toWKnife .GetData())->Force(TEX_CONSTANT); - ((CTextureData*)_toWColt .GetData())->Force(TEX_CONSTANT); - ((CTextureData*)_toWSingleShotgun .GetData())->Force(TEX_CONSTANT); - ((CTextureData*)_toWDoubleShotgun .GetData())->Force(TEX_CONSTANT); - ((CTextureData*)_toWTommygun .GetData())->Force(TEX_CONSTANT); - ((CTextureData*)_toWMinigun .GetData())->Force(TEX_CONSTANT); - ((CTextureData*)_toWRocketLauncher .GetData())->Force(TEX_CONSTANT); - ((CTextureData*)_toWGrenadeLauncher.GetData())->Force(TEX_CONSTANT); - ((CTextureData*)_toWPipeBomb .GetData())->Force(TEX_CONSTANT); - ((CTextureData*)_toWFlamer .GetData())->Force(TEX_CONSTANT); - ((CTextureData*)_toWGhostBuster .GetData())->Force(TEX_CONSTANT); - ((CTextureData*)_toWLaser .GetData())->Force(TEX_CONSTANT); - ((CTextureData*)_toWIronCannon .GetData())->Force(TEX_CONSTANT); - ((CTextureData*)_toTile .GetData())->Force(TEX_CONSTANT); - } - catch( char *strError) { - FatalError( strError); - } - -} - - -// clean up -extern void EndHUD(void) -{ - -} - + +#include "../StdH/StdH.h" + +#include +#include +#include +#include +#include +#include + + +// armor & health constants +// NOTE: these _do not_ reflect easy/tourist maxvalue adjustments. that is by design! +#define TOP_ARMOR 100 +#define TOP_HEALTH 100 + + +// cheats +extern INDEX cht_bEnable; +extern INDEX cht_bGod; +extern INDEX cht_bFly; +extern INDEX cht_bGhost; +extern INDEX cht_bInvisible; +extern FLOAT cht_fTranslationMultiplier; + +// interface control +extern INDEX hud_bShowInfo; +extern INDEX hud_bShowLatency; +extern INDEX hud_bShowMessages; +extern INDEX hud_iShowPlayers; +extern INDEX hud_iSortPlayers; +extern FLOAT hud_fOpacity; +extern FLOAT hud_fScaling; +extern FLOAT hud_tmWeaponsOnScreen; + + +// player statistics sorting keys +enum SortKeys { + PSK_NAME = 1, + PSK_HEALTH = 2, + PSK_SCORE = 3, + PSK_MANA = 4, + PSK_FRAGS = 5, + PSK_DEATHS = 6, +}; + +// where is the bar lowest value +enum BarOrientations { + BO_LEFT = 1, + BO_RIGHT = 2, + BO_UP = 3, + BO_DOWN = 4, +}; + + + +// maximal mana for master status +#define MANA_MASTER 10000 + +// drawing variables +static const CPlayer *_penPlayer; +static CPlayerWeapons *_penWeapons; +static CDrawPort *_pDP; +static PIX _pixDPWidth, _pixDPHeight; +static FLOAT _fResolutionScaling; +static FLOAT _fCustomScaling; +static ULONG _ulAlphaHUD; +static COLOR _colHUD; +static TIME _tmNow = -1.0f; +static CFontData _fdNumbersFont; + +// array for pointers of all players +CPlayer *_apenPlayers[NET_MAXGAMEPLAYERS] = {0}; + +// status bar textures +static CTextureObject _toHealth; +static CTextureObject _toArmor; +static CTextureObject _toOxygen; +static CTextureObject _toScore; +static CTextureObject _toHiScore; +static CTextureObject _toMessage; +static CTextureObject _toMana; +static CTextureObject _toFrags; +static CTextureObject _toDeaths; +// ammo textures +static CTextureObject _toAShells; +static CTextureObject _toABullets; +static CTextureObject _toARockets; +static CTextureObject _toAGrenades; +static CTextureObject _toANapalm; +static CTextureObject _toAElectricity; +static CTextureObject _toAIronBall; +// weapon textures +static CTextureObject _toWKnife; +static CTextureObject _toWColt; +static CTextureObject _toWSingleShotgun; +static CTextureObject _toWDoubleShotgun; +static CTextureObject _toWTommygun; +static CTextureObject _toWMinigun; +static CTextureObject _toWRocketLauncher; +static CTextureObject _toWGrenadeLauncher; +static CTextureObject _toWPipeBomb; +static CTextureObject _toWFlamer; +static CTextureObject _toWGhostBuster; +static CTextureObject _toWLaser; +static CTextureObject _toWIronCannon; +// tile texture (one has corners, edges and center) +static CTextureObject _toTile; + + +// all info about color transitions +struct ColorTransitionTable { + COLOR ctt_colFine; // color for values over 1.0 + COLOR ctt_colHigh; // color for values from 1.0 to 'fMedium' + COLOR ctt_colMedium; // color for values from 'fMedium' to 'fLow' + COLOR ctt_colLow; // color for values under fLow + FLOAT ctt_fMediumHigh; // when to switch to high color (normalized float!) + FLOAT ctt_fLowMedium; // when to switch to medium color (normalized float!) + BOOL ctt_bSmooth; // should colors have smooth transition +}; +static struct ColorTransitionTable _cttHUD; + + +// ammo's info structure +struct AmmoInfo { + CTextureObject *ai_ptoAmmo; + struct WeaponInfo *ai_pwiWeapon1; + struct WeaponInfo *ai_pwiWeapon2; + INDEX ai_iAmmoAmmount; + INDEX ai_iMaxAmmoAmmount; + INDEX ai_iLastAmmoAmmount; + TIME ai_tmAmmoChanged; + BOOL ai_bHasWeapon; +}; + +// weapons' info structure +struct WeaponInfo { + enum WeaponType wi_wtWeapon; + CTextureObject *wi_ptoWeapon; + struct AmmoInfo *wi_paiAmmo; + BOOL wi_bHasWeapon; +}; + +extern struct WeaponInfo _awiWeapons[18]; +static struct AmmoInfo _aaiAmmo[8] = { + { &_toAShells, &_awiWeapons[4], &_awiWeapons[5], 0, 0, 0, -9, FALSE }, + { &_toABullets, &_awiWeapons[6], &_awiWeapons[7], 0, 0, 0, -9, FALSE }, + { &_toARockets, &_awiWeapons[8], NULL, 0, 0, 0, -9, FALSE }, + { &_toAGrenades, &_awiWeapons[9], &_awiWeapons[10], 0, 0, 0, -9, FALSE }, + { &_toANapalm, &_awiWeapons[12], NULL, 0, 0, 0, -9, FALSE }, + { &_toAElectricity, &_awiWeapons[14], &_awiWeapons[15], 0, 0, 0, -9, FALSE }, + { &_toAIronBall, &_awiWeapons[16], NULL, 0, 0, 0, -9, FALSE }, + { &_toAIronBall, &_awiWeapons[17], NULL, 0, 0, 0, -9, FALSE }, +}; + +struct WeaponInfo _awiWeapons[18] = { + { WEAPON_NONE, NULL, NULL, FALSE }, // 0 + { WEAPON_KNIFE, &_toWKnife, NULL, FALSE }, // 1 + { WEAPON_COLT, &_toWColt, NULL, FALSE }, // 2 + { WEAPON_DOUBLECOLT, &_toWColt, NULL, FALSE }, // 3 + { WEAPON_SINGLESHOTGUN, &_toWSingleShotgun, &_aaiAmmo[0], FALSE }, // 4 + { WEAPON_DOUBLESHOTGUN, &_toWDoubleShotgun, &_aaiAmmo[0], FALSE }, // 5 + { WEAPON_TOMMYGUN, &_toWTommygun, &_aaiAmmo[1], FALSE }, // 6 + { WEAPON_MINIGUN, &_toWMinigun, &_aaiAmmo[1], FALSE }, // 7 + { WEAPON_ROCKETLAUNCHER, &_toWRocketLauncher, &_aaiAmmo[2], FALSE }, // 8 + { WEAPON_GRENADELAUNCHER, &_toWGrenadeLauncher, &_aaiAmmo[3], FALSE }, // 9 + { WEAPON_NONE, NULL, NULL, FALSE }, //{ WEAPON_PIPEBOMB, &_toWPipeBomb, &_aaiAmmo[3], FALSE }, // 10 + { WEAPON_NONE, NULL, NULL, FALSE }, // 11 + { WEAPON_NONE, NULL, NULL, FALSE }, //{ WEAPON_FLAMER, &_toWFlamer, &_aaiAmmo[4], FALSE }, // 12 + { WEAPON_NONE, NULL, NULL, FALSE }, // 13 + { WEAPON_LASER, &_toWLaser, &_aaiAmmo[5], FALSE }, // 14 + { WEAPON_NONE, NULL, NULL, FALSE }, //{ WEAPON_GHOSTBUSTER, &_toWGhostBuster, &_aaiAmmo[5], FALSE }, // 15 + { WEAPON_IRONCANNON, &_toWIronCannon, &_aaiAmmo[6], FALSE }, // 16 + { WEAPON_NONE, NULL, NULL, FALSE }, //{ WEAPON_NUKECANNON, &_toWNukeCannon, &_aaiAmmo[7], FALSE }, // 17 +}; + + +// compare functions for qsort() +static int qsort_CompareNames( const void *ppPEN0, const void *ppPEN1) { + CPlayer &en0 = **(CPlayer**)ppPEN0; + CPlayer &en1 = **(CPlayer**)ppPEN1; + CTString strName0 = en0.GetPlayerName(); + CTString strName1 = en1.GetPlayerName(); + return strnicmp( strName0, strName1, 8); +} + +static int qsort_CompareScores( const void *ppPEN0, const void *ppPEN1) { + CPlayer &en0 = **(CPlayer**)ppPEN0; + CPlayer &en1 = **(CPlayer**)ppPEN1; + SLONG sl0 = en0.m_psGameStats.ps_iScore; + SLONG sl1 = en1.m_psGameStats.ps_iScore; + if( sl0sl1) return -1; + else return 0; +} + +static int qsort_CompareHealth( const void *ppPEN0, const void *ppPEN1) { + CPlayer &en0 = **(CPlayer**)ppPEN0; + CPlayer &en1 = **(CPlayer**)ppPEN1; + SLONG sl0 = (SLONG)ceil(en0.GetHealth()); + SLONG sl1 = (SLONG)ceil(en1.GetHealth()); + if( sl0sl1) return -1; + else return 0; +} + +static int qsort_CompareManas( const void *ppPEN0, const void *ppPEN1) { + CPlayer &en0 = **(CPlayer**)ppPEN0; + CPlayer &en1 = **(CPlayer**)ppPEN1; + SLONG sl0 = en0.m_iMana; + SLONG sl1 = en1.m_iMana; + if( sl0sl1) return -1; + else return 0; +} + +static int qsort_CompareFrags( const void *ppPEN0, const void *ppPEN1) { + CPlayer &en0 = **(CPlayer**)ppPEN0; + CPlayer &en1 = **(CPlayer**)ppPEN1; + SLONG sl0 = en0.m_psGameStats.ps_iKills; + SLONG sl1 = en1.m_psGameStats.ps_iKills; + if( sl0sl1) return -1; + else return 0; +} + +static int qsort_CompareDeaths( const void *ppPEN0, const void *ppPEN1) { + CPlayer &en0 = **(CPlayer**)ppPEN0; + CPlayer &en1 = **(CPlayer**)ppPEN1; + SLONG sl0 = en0.m_psGameStats.ps_iDeaths; + SLONG sl1 = en1.m_psGameStats.ps_iDeaths; + if( sl0sl1) return -1; + else return 0; +} + +#if 0 // DG: unused +static int qsort_CompareLatencies( const void *ppPEN0, const void *ppPEN1) { + CPlayer &en0 = **(CPlayer**)ppPEN0; + CPlayer &en1 = **(CPlayer**)ppPEN1; + SLONG sl0 = (SLONG)ceil(en0.m_tmLatency); + SLONG sl1 = (SLONG)ceil(en1.m_tmLatency); + if( sl0sl1) return -1; + else return 0; +} +#endif // 0 (unused) + +// prepare color transitions +static void PrepareColorTransitions( COLOR colFine, COLOR colHigh, COLOR colMedium, COLOR colLow, + FLOAT fMediumHigh, FLOAT fLowMedium, BOOL bSmooth) +{ + _cttHUD.ctt_colFine = colFine; + _cttHUD.ctt_colHigh = colHigh; + _cttHUD.ctt_colMedium = colMedium; + _cttHUD.ctt_colLow = colLow; + _cttHUD.ctt_fMediumHigh = fMediumHigh; + _cttHUD.ctt_fLowMedium = fLowMedium; + _cttHUD.ctt_bSmooth = bSmooth; +} + + + +// calculates shake ammount and color value depanding on value change +#define SHAKE_TIME (2.0f) +static COLOR AddShaker( PIX const pixAmmount, INDEX const iCurrentValue, INDEX &iLastValue, + TIME &tmChanged, FLOAT &fMoverX, FLOAT &fMoverY) +{ + // update shaking if needed + fMoverX = fMoverY = 0.0f; + const TIME tmNow = _pTimer->GetLerpedCurrentTick(); + if( iCurrentValue != iLastValue) { + iLastValue = iCurrentValue; + tmChanged = tmNow; + } else { + // in case of loading (timer got reseted) + tmChanged = ClampUp( tmChanged, tmNow); + } + + // no shaker? + const TIME tmDelta = tmNow - tmChanged; + if( tmDelta > SHAKE_TIME) return NONE; + ASSERT( tmDelta>=0); + // shake, baby shake! + const FLOAT fAmmount = _fResolutionScaling * _fCustomScaling * pixAmmount; + const FLOAT fMultiplier = (SHAKE_TIME-tmDelta)/SHAKE_TIME *fAmmount; + const INDEX iRandomizer = (INDEX)(tmNow*511.0f)*fAmmount*iCurrentValue; + const FLOAT fNormRnd1 = (FLOAT)((iRandomizer ^ (iRandomizer>>9)) & 1023) * 0.0009775f; // 1/1023 - normalized + const FLOAT fNormRnd2 = (FLOAT)((iRandomizer ^ (iRandomizer>>7)) & 1023) * 0.0009775f; // 1/1023 - normalized + fMoverX = (fNormRnd1 -0.5f) * fMultiplier; + fMoverY = (fNormRnd2 -0.5f) * fMultiplier; + // clamp to adjusted ammount (pixels relative to resolution and HUD scale + fMoverX = Clamp( fMoverX, -fAmmount, fAmmount); + fMoverY = Clamp( fMoverY, -fAmmount, fAmmount); + if( tmDelta < SHAKE_TIME/3) return C_WHITE; + else return NONE; +//return FloatToInt(tmDelta*4) & 1 ? C_WHITE : NONE; +} + + +// get current color from local color transitions table +static COLOR GetCurrentColor( FLOAT fNormalizedValue) +{ + // if value is in 'low' zone just return plain 'low' alert color + if( fNormalizedValue < _cttHUD.ctt_fLowMedium) return( _cttHUD.ctt_colLow & 0xFFFFFF00); + // if value is in out of 'extreme' zone just return 'extreme' color + if( fNormalizedValue > 1.0f) return( _cttHUD.ctt_colFine & 0xFFFFFF00); + + COLOR col; + // should blend colors? + if( _cttHUD.ctt_bSmooth) + { // lets do some interpolations + FLOAT fd, f1, f2; + COLOR col1, col2; + UBYTE ubH,ubS,ubV, ubH2,ubS2,ubV2; + // determine two colors for interpolation + if( fNormalizedValue > _cttHUD.ctt_fMediumHigh) { + f1 = 1.0f; + f2 = _cttHUD.ctt_fMediumHigh; + col1 = _cttHUD.ctt_colHigh; + col2 = _cttHUD.ctt_colMedium; + } else { // fNormalizedValue > _cttHUD.ctt_fLowMedium == TRUE ! + f1 = _cttHUD.ctt_fMediumHigh; + f2 = _cttHUD.ctt_fLowMedium; + col1 = _cttHUD.ctt_colMedium; + col2 = _cttHUD.ctt_colLow; + } + // determine interpolation strength + fd = (fNormalizedValue-f2) / (f1-f2); + // convert colors to HSV + ColorToHSV( col1, ubH, ubS, ubV); + ColorToHSV( col2, ubH2, ubS2, ubV2); + // interpolate H, S and V components + ubH = (UBYTE)(ubH*fd + ubH2*(1.0f-fd)); + ubS = (UBYTE)(ubS*fd + ubS2*(1.0f-fd)); + ubV = (UBYTE)(ubV*fd + ubV2*(1.0f-fd)); + // convert HSV back to COLOR + col = HSVToColor( ubH, ubS, ubV); + } + else + { // simple color picker + col = _cttHUD.ctt_colMedium; + if( fNormalizedValue > _cttHUD.ctt_fMediumHigh) col = _cttHUD.ctt_colHigh; + } + // all done + return( col & 0xFFFFFF00); +} + + + +// fill array with players' statistics (returns current number of players in game) +extern INDEX SetAllPlayersStats( INDEX iSortKey) +{ + // determine maximum number of players for this session + INDEX iPlayers = 0; + INDEX iMaxPlayers = _penPlayer->GetMaxPlayers(); + CPlayer *penCurrent; + // loop thru potentional players + for( INDEX i=0; iGetPlayerEntity(i); + if( penCurrent==NULL) continue; + // fill in player parameters + _apenPlayers[iPlayers] = penCurrent; + // advance to next real player + iPlayers++; + } + // sort statistics by some key if needed + switch( iSortKey) { + case PSK_NAME: qsort( _apenPlayers, iPlayers, sizeof(CPlayer*), qsort_CompareNames); break; + case PSK_SCORE: qsort( _apenPlayers, iPlayers, sizeof(CPlayer*), qsort_CompareScores); break; + case PSK_HEALTH: qsort( _apenPlayers, iPlayers, sizeof(CPlayer*), qsort_CompareHealth); break; + case PSK_MANA: qsort( _apenPlayers, iPlayers, sizeof(CPlayer*), qsort_CompareManas); break; + case PSK_FRAGS: qsort( _apenPlayers, iPlayers, sizeof(CPlayer*), qsort_CompareFrags); break; + case PSK_DEATHS: qsort( _apenPlayers, iPlayers, sizeof(CPlayer*), qsort_CompareDeaths); break; + default: break; // invalid or NONE key specified so do nothing + } + // all done + return iPlayers; +} + + + +// ----------------------- drawing functions + +// draw border with filter +static void HUD_DrawBorder( FLOAT fCenterX, FLOAT fCenterY, FLOAT fSizeX, FLOAT fSizeY, COLOR colTiles) +{ + // determine location + const FLOAT fCenterI = fCenterX*_pixDPWidth / 640.0f; + const FLOAT fCenterJ = fCenterY*_pixDPHeight / (480.0f * _pDP->dp_fWideAdjustment); + const FLOAT fSizeI = _fResolutionScaling*fSizeX; + const FLOAT fSizeJ = _fResolutionScaling*fSizeY; + const FLOAT fTileSize = 8*_fResolutionScaling*_fCustomScaling; + // determine exact positions + const FLOAT fLeft = fCenterI - fSizeI/2 -1; + const FLOAT fRight = fCenterI + fSizeI/2 +1; + const FLOAT fUp = fCenterJ - fSizeJ/2 -1; + const FLOAT fDown = fCenterJ + fSizeJ/2 +1; + const FLOAT fLeftEnd = fLeft + fTileSize; + const FLOAT fRightBeg = fRight - fTileSize; + const FLOAT fUpEnd = fUp + fTileSize; + const FLOAT fDownBeg = fDown - fTileSize; + // prepare texture + colTiles |= _ulAlphaHUD; + // put corners + _pDP->InitTexture( &_toTile, TRUE); // clamping on! + _pDP->AddTexture( fLeft, fUp, fLeftEnd, fUpEnd, colTiles); + _pDP->AddTexture( fRight,fUp, fRightBeg,fUpEnd, colTiles); + _pDP->AddTexture( fRight,fDown, fRightBeg,fDownBeg, colTiles); + _pDP->AddTexture( fLeft, fDown, fLeftEnd, fDownBeg, colTiles); + // put edges + _pDP->AddTexture( fLeftEnd,fUp, fRightBeg,fUpEnd, 0.4f,0.0f, 0.6f,1.0f, colTiles); + _pDP->AddTexture( fLeftEnd,fDown, fRightBeg,fDownBeg, 0.4f,0.0f, 0.6f,1.0f, colTiles); + _pDP->AddTexture( fLeft, fUpEnd, fLeftEnd, fDownBeg, 0.0f,0.4f, 1.0f,0.6f, colTiles); + _pDP->AddTexture( fRight, fUpEnd, fRightBeg,fDownBeg, 0.0f,0.4f, 1.0f,0.6f, colTiles); + // put center + _pDP->AddTexture( fLeftEnd, fUpEnd, fRightBeg, fDownBeg, 0.4f,0.4f, 0.6f,0.6f, colTiles); + _pDP->FlushRenderingQueue(); +} + + +// draw icon texture (if color = NONE, use colortransitions structure) +static void HUD_DrawIcon( FLOAT fCenterX, FLOAT fCenterY, CTextureObject &toIcon, + COLOR colDefault, FLOAT fNormValue, BOOL bBlink) +{ + // determine color + COLOR col = colDefault; + if( col==NONE) col = GetCurrentColor( fNormValue); + // determine blinking state + if( bBlink && fNormValue<=(_cttHUD.ctt_fLowMedium/2)) { + // activate blinking only if value is <= half the low edge + INDEX iCurrentTime = (INDEX)(_tmNow*4); + if( iCurrentTime&1) col = C_vdGRAY; + } + // determine location + const FLOAT fCenterI = fCenterX*_pixDPWidth / 640.0f; + const FLOAT fCenterJ = fCenterY*_pixDPHeight / (480.0f * _pDP->dp_fWideAdjustment); + // determine dimensions + CTextureData *ptd = (CTextureData*)toIcon.GetData(); + const FLOAT fHalfSizeI = _fResolutionScaling*_fCustomScaling * ptd->GetPixWidth() *0.5f; + const FLOAT fHalfSizeJ = _fResolutionScaling*_fCustomScaling * ptd->GetPixHeight() *0.5f; + // done + _pDP->InitTexture( &toIcon); + _pDP->AddTexture( fCenterI-fHalfSizeI, fCenterJ-fHalfSizeJ, + fCenterI+fHalfSizeI, fCenterJ+fHalfSizeJ, col|_ulAlphaHUD); + _pDP->FlushRenderingQueue(); +} + + +// draw text (or numbers, whatever) +static void HUD_DrawText( FLOAT fCenterX, FLOAT fCenterY, const CTString &strText, + COLOR colDefault, FLOAT fNormValue) +{ + // determine color + COLOR col = colDefault; + if( col==NONE) col = GetCurrentColor( fNormValue); + // determine location + PIX pixCenterI = (PIX)(fCenterX*_pixDPWidth / 640.0f); + PIX pixCenterJ = (PIX)(fCenterY*_pixDPHeight / (480.0f * _pDP->dp_fWideAdjustment)); + // done + _pDP->SetTextScaling( _fResolutionScaling*_fCustomScaling); + _pDP->PutTextCXY( strText, pixCenterI, pixCenterJ, col|_ulAlphaHUD); +} + + +// draw bar +static void HUD_DrawBar( FLOAT fCenterX, FLOAT fCenterY, PIX pixSizeX, PIX pixSizeY, + enum BarOrientations eBarOrientation, COLOR colDefault, FLOAT fNormValue) +{ + // determine color + COLOR col = colDefault; + if( col==NONE) col = GetCurrentColor( fNormValue); + // determine location and size + PIX pixCenterI = (PIX)(fCenterX*_pixDPWidth / 640.0f); + PIX pixCenterJ = (PIX)(fCenterY*_pixDPHeight / (480.0f * _pDP->dp_fWideAdjustment)); + PIX pixSizeI = (PIX)(_fResolutionScaling*pixSizeX); + PIX pixSizeJ = (PIX)(_fResolutionScaling*pixSizeY); + // fill bar background area + PIX pixLeft = pixCenterI-pixSizeI/2; + PIX pixUpper = pixCenterJ-pixSizeJ/2; + // determine bar position and inner size + switch( eBarOrientation) { + case BO_UP: + pixSizeJ *= fNormValue; + break; + case BO_DOWN: + pixUpper = pixUpper + (PIX)ceil(pixSizeJ * (1.0f-fNormValue)); + pixSizeJ *= fNormValue; + break; + case BO_LEFT: + pixSizeI *= fNormValue; + break; + case BO_RIGHT: + pixLeft = pixLeft + (PIX)ceil(pixSizeI * (1.0f-fNormValue)); + pixSizeI *= fNormValue; + break; + } + // done + _pDP->Fill( pixLeft, pixUpper, pixSizeI, pixSizeJ, col|_ulAlphaHUD); +} + + +// helper functions + +// fill weapon and ammo table with current state +static void FillWeaponAmmoTables(void) +{ + // ammo quantities + _aaiAmmo[0].ai_iAmmoAmmount = _penWeapons->m_iShells; + _aaiAmmo[0].ai_iMaxAmmoAmmount = _penWeapons->m_iMaxShells; + _aaiAmmo[1].ai_iAmmoAmmount = _penWeapons->m_iBullets; + _aaiAmmo[1].ai_iMaxAmmoAmmount = _penWeapons->m_iMaxBullets; + _aaiAmmo[2].ai_iAmmoAmmount = _penWeapons->m_iRockets; + _aaiAmmo[2].ai_iMaxAmmoAmmount = _penWeapons->m_iMaxRockets; + _aaiAmmo[3].ai_iAmmoAmmount = _penWeapons->m_iGrenades; + _aaiAmmo[3].ai_iMaxAmmoAmmount = _penWeapons->m_iMaxGrenades; + _aaiAmmo[4].ai_iAmmoAmmount = 0;//_penWeapons->m_iNapalm; + _aaiAmmo[4].ai_iMaxAmmoAmmount = 0;//_penWeapons->m_iMaxNapalm; + _aaiAmmo[5].ai_iAmmoAmmount = _penWeapons->m_iElectricity; + _aaiAmmo[5].ai_iMaxAmmoAmmount = _penWeapons->m_iMaxElectricity; + _aaiAmmo[6].ai_iAmmoAmmount = _penWeapons->m_iIronBalls; + _aaiAmmo[6].ai_iMaxAmmoAmmount = _penWeapons->m_iMaxIronBalls; + _aaiAmmo[7].ai_iAmmoAmmount = 0;//_penWeapons->m_iNukeBalls; + _aaiAmmo[7].ai_iMaxAmmoAmmount = 0;//_penWeapons->m_iMaxNukeBalls; + + // prepare ammo table for weapon possesion + INDEX i, iAvailableWeapons = _penWeapons->m_iAvailableWeapons; + for( i=0; i<8; i++) _aaiAmmo[i].ai_bHasWeapon = FALSE; + // weapon possesion + for( i=WEAPON_NONE+1; iai_bHasWeapon |= _awiWeapons[i].wi_bHasWeapon; + } + } +} + + + +// main + +// render interface (frontend) to drawport +// (units are in pixels for 640x480 resolution - for other res HUD will be scalled automatically) +extern void DrawHUD( const CPlayer *penPlayerCurrent, CDrawPort *pdpCurrent, BOOL bSnooping) +{ + // no player - no info, sorry + if( penPlayerCurrent==NULL || (penPlayerCurrent->GetFlags()&ENF_DELETED)) return; + + // find last values in case of predictor + CPlayer *penLast = (CPlayer*)penPlayerCurrent; + if( penPlayerCurrent->IsPredictor()) penLast = (CPlayer*)(((CPlayer*)penPlayerCurrent)->GetPredicted()); + ASSERT( penLast!=NULL); + if( penLast==NULL) return; // !!!! just in case + + // cache local variables + hud_fOpacity = Clamp( hud_fOpacity, 0.1f, 1.0f); + hud_fScaling = Clamp( hud_fScaling, 0.5f, 1.2f); + _penPlayer = penPlayerCurrent; + _penWeapons = (CPlayerWeapons*)&*_penPlayer->m_penWeapons; + _pDP = pdpCurrent; + _pixDPWidth = _pDP->GetWidth(); + _pixDPHeight = _pDP->GetHeight(); + _fCustomScaling = hud_fScaling; + _fResolutionScaling = (FLOAT)_pixDPWidth /640.0f; + _colHUD = C_GREEN; + _ulAlphaHUD = NormFloatToByte(hud_fOpacity); + _tmNow = _pTimer->CurrentTick(); + + // set HUD colorization; + COLOR colMax = _colHUD; + COLOR colTop = _colHUD; + COLOR colMid = _colHUD; + + // adjust borders color in case of spying mode + COLOR colBorder = _colHUD; + if( bSnooping) { + UBYTE ubR,ubG,ubB; + ColorToRGB( colBorder, ubR,ubG,ubB); + colBorder = RGBToColor( ubG,ubB,ubR); // shift and xor color components + if( ((ULONG)(_tmNow*5))&1) { + colBorder = (colBorder>>1) & 0x7F7F7F00; // darken flash and scale + _fCustomScaling *= 0.933f; + } + } + + // prepare font and text dimensions + CTString strValue; + PIX pixCharWidth; + FLOAT fValue, fNormValue, fCol, fRow; + _pDP->SetFont( &_fdNumbersFont); + pixCharWidth = _fdNumbersFont.GetWidth() + _fdNumbersFont.GetCharSpacing() +1; + FLOAT fChrUnit = pixCharWidth * _fCustomScaling; + + const PIX pixTopBound = 6; + const PIX pixLeftBound = 6; + const PIX pixBottomBound = (480 * _pDP->dp_fWideAdjustment) -pixTopBound; + const PIX pixRightBound = 640-pixLeftBound; + FLOAT fOneUnit = (32+0) * _fCustomScaling; // unit size + FLOAT fAdvUnit = (32+4) * _fCustomScaling; // unit advancer + FLOAT fNextUnit = (32+8) * _fCustomScaling; // unit advancer + FLOAT fHalfUnit = fOneUnit * 0.5f; + FLOAT fMoverX, fMoverY; + COLOR colDefault; + + // prepare and draw health info + fValue = ClampDn( _penPlayer->GetHealth(), 0.0f); // never show negative health + fNormValue = fValue/TOP_HEALTH; + strValue.PrintF( "%d", (SLONG)ceil(fValue)); + PrepareColorTransitions( colMax, colTop, colMid, C_RED, 0.5f, 0.25f, FALSE); + fRow = pixBottomBound-fHalfUnit; + fCol = pixLeftBound+fHalfUnit; + colDefault = AddShaker( 5, fValue, penLast->m_iLastHealth, penLast->m_tmHealthChanged, fMoverX, fMoverY); + HUD_DrawBorder( fCol+fMoverX, fRow+fMoverY, fOneUnit, fOneUnit, colBorder); + fCol += fAdvUnit+fChrUnit*3/2 -fHalfUnit; + HUD_DrawBorder( fCol, fRow, fChrUnit*3, fOneUnit, colBorder); + HUD_DrawText( fCol, fRow, strValue, colDefault, fNormValue); + fCol -= fAdvUnit+fChrUnit*3/2 -fHalfUnit; + HUD_DrawIcon( fCol+fMoverX, fRow+fMoverY, _toHealth, _colHUD, fNormValue, TRUE); + + // prepare and draw armor info (eventually) + fValue = _penPlayer->m_fArmor; + if( fValue > 0.0f) { + fNormValue = fValue/TOP_ARMOR; + strValue.PrintF( "%d", (SLONG)ceil(fValue)); + PrepareColorTransitions( colMax, colTop, colMid, C_lGRAY, 0.5f, 0.25f, FALSE); + fRow = pixBottomBound- (fNextUnit+fHalfUnit);//*_pDP->dp_fWideAdjustment; + fCol = pixLeftBound+ fHalfUnit; + colDefault = AddShaker( 3, fValue, penLast->m_iLastArmor, penLast->m_tmArmorChanged, fMoverX, fMoverY); + HUD_DrawBorder( fCol+fMoverX, fRow+fMoverY, fOneUnit, fOneUnit, colBorder); + fCol += fAdvUnit+fChrUnit*3/2 -fHalfUnit; + HUD_DrawBorder( fCol, fRow, fChrUnit*3, fOneUnit, colBorder); + HUD_DrawText( fCol, fRow, strValue, NONE, fNormValue); + fCol -= fAdvUnit+fChrUnit*3/2 -fHalfUnit; + HUD_DrawIcon( fCol+fMoverX, fRow+fMoverY, _toArmor, _colHUD, fNormValue, FALSE); + } + + // prepare and draw ammo and weapon info + CTextureObject *ptoCurrentAmmo=NULL, *ptoCurrentWeapon=NULL, *ptoWantedWeapon=NULL; + INDEX iCurrentWeapon = _penWeapons->m_iCurrentWeapon; + INDEX iWantedWeapon = _penWeapons->m_iWantedWeapon; + // determine corresponding ammo and weapon texture component + ptoCurrentWeapon = _awiWeapons[iCurrentWeapon].wi_ptoWeapon; + ptoWantedWeapon = _awiWeapons[iWantedWeapon].wi_ptoWeapon; + + AmmoInfo *paiCurrent = _awiWeapons[iCurrentWeapon].wi_paiAmmo; + if( paiCurrent!=NULL) ptoCurrentAmmo = paiCurrent->ai_ptoAmmo; + + // draw complete weapon info if knife isn't current weapon + if( ptoCurrentAmmo!=NULL && !GetSP()->sp_bInfiniteAmmo) { + // determine ammo quantities + FLOAT fMaxValue = _penWeapons->GetMaxAmmo(); + fValue = _penWeapons->GetAmmo(); + fNormValue = fValue / fMaxValue; + strValue.PrintF( "%d", (SLONG)ceil(fValue)); + PrepareColorTransitions( colMax, colTop, colMid, C_RED, 0.5f, 0.25f, FALSE); + BOOL bDrawAmmoIcon = _fCustomScaling<=1.0f; + // draw ammo, value and weapon + fRow = pixBottomBound-fHalfUnit; + fCol = 175 + fHalfUnit; + colDefault = AddShaker( 4, fValue, penLast->m_iLastAmmo, penLast->m_tmAmmoChanged, fMoverX, fMoverY); + HUD_DrawBorder( fCol+fMoverX, fRow+fMoverY, fOneUnit, fOneUnit, colBorder); + fCol += fAdvUnit+fChrUnit*3/2 -fHalfUnit; + HUD_DrawBorder( fCol, fRow, fChrUnit*3, fOneUnit, colBorder); + if( bDrawAmmoIcon) { + fCol += fAdvUnit+fChrUnit*3/2 -fHalfUnit; + HUD_DrawBorder( fCol, fRow, fOneUnit, fOneUnit, colBorder); + HUD_DrawIcon( fCol, fRow, *ptoCurrentAmmo, _colHUD, fNormValue, TRUE); + fCol -= fAdvUnit+fChrUnit*3/2 -fHalfUnit; + } + HUD_DrawText( fCol, fRow, strValue, colDefault, fNormValue); + fCol -= fAdvUnit+fChrUnit*3/2 -fHalfUnit; + HUD_DrawIcon( fCol+fMoverX, fRow+fMoverY, *ptoCurrentWeapon, _colHUD, fNormValue, !bDrawAmmoIcon); + } else if( ptoCurrentWeapon!=NULL) { + // draw only knife or colt icons (ammo is irrelevant) + fRow = pixBottomBound-fHalfUnit; + fCol = 205 + fHalfUnit; + HUD_DrawBorder( fCol, fRow, fOneUnit, fOneUnit, colBorder); + HUD_DrawIcon( fCol, fRow, *ptoCurrentWeapon, _colHUD, fNormValue, FALSE); + } + + + // display all ammo infos + INDEX i; + FLOAT fAdv; + COLOR colIcon, colBar; + PrepareColorTransitions( colMax, colTop, colMid, C_RED, 0.5f, 0.25f, FALSE); + // reduce the size of icon slightly + _fCustomScaling = ClampDn( _fCustomScaling*0.8f, 0.5f); + const FLOAT fOneUnitS = fOneUnit *0.8f; + const FLOAT fAdvUnitS = fAdvUnit *0.8f; + //const FLOAT fNextUnitS = fNextUnit *0.8f; + const FLOAT fHalfUnitS = fHalfUnit *0.8f; + + // prepare postition and ammo quantities + fRow = pixBottomBound-fHalfUnitS; + fCol = pixRightBound -fHalfUnitS; + const FLOAT fBarPos = fHalfUnitS*0.7f; + FillWeaponAmmoTables(); + + // loop thru all ammo types + if (!GetSP()->sp_bInfiniteAmmo) { + for( i=7; i>=0; i--) { + // if no ammo and hasn't got that weapon - just skip this ammo + AmmoInfo &ai = _aaiAmmo[i]; + ASSERT( ai.ai_iAmmoAmmount>=0); + if( ai.ai_iAmmoAmmount==0 && !ai.ai_bHasWeapon) continue; + // display ammo info + colIcon = _colHUD; + if( ai.ai_iAmmoAmmount==0) colIcon = C_GRAY; + if( ptoCurrentAmmo == ai.ai_ptoAmmo) colIcon = C_WHITE; + fNormValue = (FLOAT)ai.ai_iAmmoAmmount / ai.ai_iMaxAmmoAmmount; + colBar = AddShaker( 4, ai.ai_iAmmoAmmount, ai.ai_iLastAmmoAmmount, ai.ai_tmAmmoChanged, fMoverX, fMoverY); + HUD_DrawBorder( fCol, fRow+fMoverY, fOneUnitS, fOneUnitS, colBorder); + HUD_DrawIcon( fCol, fRow+fMoverY, *_aaiAmmo[i].ai_ptoAmmo, colIcon, fNormValue, FALSE); + HUD_DrawBar( fCol+fBarPos, fRow+fMoverY, fOneUnitS/5, fOneUnitS-2, BO_DOWN, colBar, fNormValue); + // advance to next position + fCol -= fAdvUnitS; + } + } + + // if weapon change is in progress + _fCustomScaling = hud_fScaling; + hud_tmWeaponsOnScreen = Clamp( hud_tmWeaponsOnScreen, 0.0f, 10.0f); + if( (_tmNow - _penWeapons->m_tmWeaponChangeRequired) < hud_tmWeaponsOnScreen) { + // determine number of weapons that player has + INDEX ctWeapons = 0; + for( i=WEAPON_NONE+1; iai_iAmmoAmmount==0) colIcon = C_dGRAY; + if( ptoWantedWeapon == _awiWeapons[i].wi_ptoWeapon) colIcon = C_WHITE; + HUD_DrawBorder( fCol, fRow, fOneUnit, fOneUnit, colIcon); + HUD_DrawIcon( fCol, fRow, *_awiWeapons[i].wi_ptoWeapon, colIcon, 1.0f, FALSE); + // advance to next position + fCol += fAdvUnit; + } + } + + const FLOAT fUpperSize = ClampDn(_fCustomScaling*0.5f, 0.5f)/_fCustomScaling; + _fCustomScaling*=fUpperSize; + ASSERT( _fCustomScaling>=0.5f); + fChrUnit *= fUpperSize; + fOneUnit *= fUpperSize; + fHalfUnit *= fUpperSize; + fAdvUnit *= fUpperSize; + fNextUnit *= fUpperSize; + + // draw oxygen info if needed + BOOL bOxygenOnScreen = FALSE; + fValue = _penPlayer->en_tmMaxHoldBreath - (_pTimer->CurrentTick() - _penPlayer->en_tmLastBreathed); + if( _penPlayer->IsConnected() && (_penPlayer->GetFlags()&ENF_ALIVE) && fValue<30.0f) { + // prepare and draw oxygen info + fRow = pixTopBound + fOneUnit + fNextUnit; + fCol = 280.0f; + fAdv = fAdvUnit + fOneUnit*4/2 - fHalfUnit; + PrepareColorTransitions( colMax, colTop, colMid, C_RED, 0.5f, 0.25f, FALSE); + fNormValue = fValue/30.0f; + fNormValue = ClampDn(fNormValue, 0.0f); + HUD_DrawBorder( fCol, fRow, fOneUnit, fOneUnit, colBorder); + HUD_DrawBorder( fCol+fAdv, fRow, fOneUnit*4, fOneUnit, colBorder); + HUD_DrawBar( fCol+fAdv, fRow, fOneUnit*4*0.975, fOneUnit*0.9375, BO_LEFT, NONE, fNormValue); + HUD_DrawIcon( fCol, fRow, _toOxygen, _colHUD, fNormValue, TRUE); + bOxygenOnScreen = TRUE; + } + + // draw boss energy if needed + if( _penPlayer->m_penMainMusicHolder!=NULL) { + CMusicHolder &mh = (CMusicHolder&)*_penPlayer->m_penMainMusicHolder; + fNormValue = 0; + + if( mh.m_penBoss!=NULL && (mh.m_penBoss->en_ulFlags&ENF_ALIVE)) { + CEnemyBase &eb = (CEnemyBase&)*mh.m_penBoss; + ASSERT( eb.m_fMaxHealth>0); + fValue = eb.GetHealth(); + fNormValue = fValue/eb.m_fMaxHealth; + } + if( mh.m_penCounter!=NULL) { + CEnemyCounter &ec = (CEnemyCounter&)*mh.m_penCounter; + if (ec.m_iCount>0) { + fValue = ec.m_iCount; + fNormValue = fValue/ec.m_iCountFrom; + } + } + if (fNormValue>0) { + // prepare and draw boss energy info + PrepareColorTransitions( colMax, colTop, colMid, C_RED, 0.5f, 0.25f, FALSE); + fRow = pixTopBound + fOneUnit + fNextUnit; + fCol = 184.0f; + fAdv = fAdvUnit+ fOneUnit*16/2 -fHalfUnit; + if( bOxygenOnScreen) fRow += fNextUnit; + HUD_DrawBorder( fCol, fRow, fOneUnit, fOneUnit, colBorder); + HUD_DrawBorder( fCol+fAdv, fRow, fOneUnit*16, fOneUnit, colBorder); + HUD_DrawBar( fCol+fAdv, fRow, fOneUnit*16*0.995, fOneUnit*0.9375, BO_LEFT, NONE, fNormValue); + HUD_DrawIcon( fCol, fRow, _toHealth, _colHUD, fNormValue, FALSE); + } + } + + // determine scaling of normal text and play mode + const FLOAT fTextScale = (_fResolutionScaling+1) *0.5f; + const BOOL bSinglePlay = GetSP()->sp_bSinglePlayer; + const BOOL bCooperative = GetSP()->sp_bCooperative && !bSinglePlay; + const BOOL bScoreMatch = !GetSP()->sp_bCooperative && !GetSP()->sp_bUseFrags; + const BOOL bFragMatch = !GetSP()->sp_bCooperative && GetSP()->sp_bUseFrags; + COLOR colMana, colFrags, colDeaths, colHealth, colArmor; + COLOR colScore = _colHUD; + INDEX iScoreSum = 0; + + // if not in single player mode, we'll have to calc (and maybe printout) other players' info + if( !bSinglePlay) + { + // set font and prepare font parameters + _pfdDisplayFont->SetVariableWidth(); + _pDP->SetFont( _pfdDisplayFont); + _pDP->SetTextScaling( fTextScale); + FLOAT fCharHeight = (_pfdDisplayFont->GetHeight()-2)*fTextScale; + // generate and sort by mana list of active players + BOOL bMaxScore=TRUE, bMaxMana=TRUE, bMaxFrags=TRUE, bMaxDeaths=TRUE; + hud_iSortPlayers = Clamp( hud_iSortPlayers, -1, 6); + SortKeys eKey = (SortKeys)hud_iSortPlayers; + if (hud_iSortPlayers==-1) { + if (bCooperative) eKey = PSK_HEALTH; + else if (bScoreMatch) eKey = PSK_SCORE; + else if (bFragMatch) eKey = PSK_FRAGS; + else { ASSERT(FALSE); eKey = PSK_NAME; } + } + if( bCooperative) eKey = (SortKeys)Clamp( (INDEX)eKey, 0, 3); + if( eKey==PSK_HEALTH && (bScoreMatch || bFragMatch)) { eKey = PSK_NAME; }; // prevent health snooping in deathmatch + INDEX iPlayers = SetAllPlayersStats(eKey); + // loop thru players + for( INDEX i=0; iGetPlayerName(); + const INDEX iScore = penPlayer->m_psGameStats.ps_iScore; + const INDEX iMana = penPlayer->m_iMana; + const INDEX iFrags = penPlayer->m_psGameStats.ps_iKills; + const INDEX iDeaths = penPlayer->m_psGameStats.ps_iDeaths; + const INDEX iHealth = ClampDn( (INDEX)ceil( penPlayer->GetHealth()), 0); + const INDEX iArmor = ClampDn( (INDEX)ceil( penPlayer->m_fArmor), 0); + CTString strScore, strMana, strFrags, strDeaths, strHealth, strArmor; + strScore.PrintF( "%d", iScore); + strMana.PrintF( "%d", iMana); + strFrags.PrintF( "%d", iFrags); + strDeaths.PrintF( "%d", iDeaths); + strHealth.PrintF( "%d", iHealth); + strArmor.PrintF( "%d", iArmor); + // detemine corresponding colors + colHealth = C_mlRED; + colMana = colScore = colFrags = colDeaths = colArmor = C_lGRAY; + if( iMana > _penPlayer->m_iMana) { bMaxMana = FALSE; colMana = C_WHITE; } + if( iScore > _penPlayer->m_psGameStats.ps_iScore) { bMaxScore = FALSE; colScore = C_WHITE; } + if( iFrags > _penPlayer->m_psGameStats.ps_iKills) { bMaxFrags = FALSE; colFrags = C_WHITE; } + if( iDeaths > _penPlayer->m_psGameStats.ps_iDeaths) { bMaxDeaths = FALSE; colDeaths = C_WHITE; } + if( penPlayer==_penPlayer) colScore = colMana = colFrags = colDeaths = _colHUD; // current player + if( iHealth>25) colHealth = _colHUD; + if( iArmor >25) colArmor = _colHUD; + // eventually print it out + if( hud_iShowPlayers==1 || hud_iShowPlayers==-1) { + // printout location and info aren't the same for deathmatch and coop play + const FLOAT fCharWidth = (PIX)((_pfdDisplayFont->GetWidth()-2) *fTextScale); + if( bCooperative) { + _pDP->PutTextR( strName+":", _pixDPWidth-8*fCharWidth, fCharHeight*i+fOneUnit*2, colScore |_ulAlphaHUD); + _pDP->PutText( "/", _pixDPWidth-4*fCharWidth, fCharHeight*i+fOneUnit*2, _colHUD |_ulAlphaHUD); + _pDP->PutTextC( strHealth, _pixDPWidth-6*fCharWidth, fCharHeight*i+fOneUnit*2, colHealth|_ulAlphaHUD); + _pDP->PutTextC( strArmor, _pixDPWidth-2*fCharWidth, fCharHeight*i+fOneUnit*2, colArmor |_ulAlphaHUD); + } else if( bScoreMatch) { + _pDP->PutTextR( strName+":", _pixDPWidth-12*fCharWidth, fCharHeight*i+fOneUnit*2, _colHUD |_ulAlphaHUD); + _pDP->PutText( "/", _pixDPWidth- 5*fCharWidth, fCharHeight*i+fOneUnit*2, _colHUD |_ulAlphaHUD); + _pDP->PutTextC( strScore, _pixDPWidth- 8*fCharWidth, fCharHeight*i+fOneUnit*2, colScore|_ulAlphaHUD); + _pDP->PutTextC( strMana, _pixDPWidth- 2*fCharWidth, fCharHeight*i+fOneUnit*2, colMana |_ulAlphaHUD); + } else { // fragmatch! + _pDP->PutTextR( strName+":", _pixDPWidth-8*fCharWidth, fCharHeight*i+fOneUnit*2, _colHUD |_ulAlphaHUD); + _pDP->PutText( "/", _pixDPWidth-4*fCharWidth, fCharHeight*i+fOneUnit*2, _colHUD |_ulAlphaHUD); + _pDP->PutTextC( strFrags, _pixDPWidth-6*fCharWidth, fCharHeight*i+fOneUnit*2, colFrags |_ulAlphaHUD); + _pDP->PutTextC( strDeaths, _pixDPWidth-2*fCharWidth, fCharHeight*i+fOneUnit*2, colDeaths|_ulAlphaHUD); + } + } + // calculate summ of scores (for coop mode) + iScoreSum += iScore; + } + + // prepare color for local player printouts + bMaxScore ? colScore = C_WHITE : colScore = C_lGRAY; + bMaxMana ? colMana = C_WHITE : colMana = C_lGRAY; + bMaxFrags ? colFrags = C_WHITE : colFrags = C_lGRAY; + bMaxDeaths ? colDeaths = C_WHITE : colDeaths = C_lGRAY; + } + + // printout player latency if needed + if( hud_bShowLatency) { + CTString strLatency; + strLatency.PrintF( "%4.0fms", _penPlayer->m_tmLatency*1000.0f); + PIX pixFontHeight = (PIX)(_pfdDisplayFont->GetHeight() *fTextScale +fTextScale+1); + _pfdDisplayFont->SetFixedWidth(); + _pDP->SetFont( _pfdDisplayFont); + _pDP->SetTextScaling( fTextScale); + _pDP->SetTextCharSpacing( -2.0f*fTextScale); + _pDP->PutTextR( strLatency, _pixDPWidth, _pixDPHeight-pixFontHeight, C_WHITE|CT_OPAQUE); + } + // restore font defaults + _pfdDisplayFont->SetVariableWidth(); + _pDP->SetFont( &_fdNumbersFont); + _pDP->SetTextCharSpacing(1); + + // prepare output strings and formats depending on game type + FLOAT fWidthAdj = 8; + INDEX iScore = _penPlayer->m_psGameStats.ps_iScore; + INDEX iMana = _penPlayer->m_iMana; + if( bFragMatch) { + fWidthAdj = 4; + iScore = _penPlayer->m_psGameStats.ps_iKills; + iMana = _penPlayer->m_psGameStats.ps_iDeaths; + } else if( bCooperative) { + // in case of coop play, show squad (common) score + iScore = iScoreSum; + } + + // prepare and draw score or frags info + strValue.PrintF( "%d", iScore); + fRow = pixTopBound +fHalfUnit; + fCol = pixLeftBound +fHalfUnit; + fAdv = fAdvUnit+ fChrUnit*fWidthAdj/2 -fHalfUnit; + HUD_DrawBorder( fCol, fRow, fOneUnit, fOneUnit, colBorder); + HUD_DrawBorder( fCol+fAdv, fRow, fChrUnit*fWidthAdj, fOneUnit, colBorder); + HUD_DrawText( fCol+fAdv, fRow, strValue, colScore, 1.0f); + HUD_DrawIcon( fCol, fRow, _toFrags, colScore, 1.0f, FALSE); + + // eventually draw mana info + if( bScoreMatch || bFragMatch) { + strValue.PrintF( "%d", iMana); + fRow = pixTopBound + fNextUnit+fHalfUnit; + fCol = pixLeftBound + fHalfUnit; + fAdv = fAdvUnit+ fChrUnit*fWidthAdj/2 -fHalfUnit; + HUD_DrawBorder( fCol, fRow, fOneUnit, fOneUnit, colBorder); + HUD_DrawBorder( fCol+fAdv, fRow, fChrUnit*fWidthAdj, fOneUnit, colBorder); + HUD_DrawText( fCol+fAdv, fRow, strValue, colMana, 1.0f); + HUD_DrawIcon( fCol, fRow, _toDeaths, colMana, 1.0f, FALSE); + } + + // if single player or cooperative mode + if( bSinglePlay || bCooperative) + { + // prepare and draw hiscore info + strValue.PrintF( "%d", Max(_penPlayer->m_iHighScore, _penPlayer->m_psGameStats.ps_iScore)); + BOOL bBeating = _penPlayer->m_psGameStats.ps_iScore>_penPlayer->m_iHighScore; + fRow = pixTopBound+fHalfUnit; + fCol = 320.0f-fOneUnit-fChrUnit*8/2; + fAdv = fAdvUnit+ fChrUnit*8/2 -fHalfUnit; + HUD_DrawBorder( fCol, fRow, fOneUnit, fOneUnit, colBorder); + HUD_DrawBorder( fCol+fAdv, fRow, fChrUnit*8, fOneUnit, colBorder); + HUD_DrawText( fCol+fAdv, fRow, strValue, NONE, bBeating ? 0.0f : 1.0f); + HUD_DrawIcon( fCol, fRow, _toHiScore, _colHUD, 1.0f, FALSE); + + // prepare and draw unread messages + if( hud_bShowMessages && _penPlayer->m_ctUnreadMessages>0) { + strValue.PrintF( "%d", _penPlayer->m_ctUnreadMessages); + fRow = pixTopBound+fHalfUnit; + fCol = pixRightBound-fHalfUnit-fAdvUnit-fChrUnit*4; + const FLOAT tmIn = 0.5f; + const FLOAT tmOut = 0.5f; + const FLOAT tmStay = 2.0f; + FLOAT tmDelta = _pTimer->GetLerpedCurrentTick()-_penPlayer->m_tmAnimateInbox; + COLOR col = _colHUD; + if (tmDelta>0 && tmDelta<(tmIn+tmStay+tmOut) && bSinglePlay) { + FLOAT fRatio = 0.0f; + if (tmDeltatmIn+tmStay) { + fRatio = (tmIn+tmStay+tmOut-tmDelta)/tmOut; + } else { + fRatio = 1.0f; + } + fRow+=fAdvUnit*5*fRatio; + fCol-=fAdvUnit*15*fRatio; + col = LerpColor(_colHUD, C_WHITE|0xFF, fRatio); + } + fAdv = fAdvUnit+ fChrUnit*4/2 -fHalfUnit; + HUD_DrawBorder( fCol, fRow, fOneUnit, fOneUnit, col); + HUD_DrawBorder( fCol+fAdv, fRow, fChrUnit*4, fOneUnit, col); + HUD_DrawText( fCol+fAdv, fRow, strValue, col, 1.0f); + HUD_DrawIcon( fCol, fRow, _toMessage, col, 0.0f, TRUE); + } + } + + // draw cheat modes + if( GetSP()->sp_ctMaxPlayers==1) { + INDEX iLine=1; + ULONG ulAlpha = sin(_tmNow*16)*96 +128; + PIX pixFontHeight = _pfdConsoleFont->fd_pixCharHeight; + const COLOR colCheat = _colHUD; + _pDP->SetFont( _pfdConsoleFont); + _pDP->SetTextScaling( 1.0f); + const FLOAT fchtTM = cht_fTranslationMultiplier; // for text formatting sake :) + if( fchtTM > 1.0f) { _pDP->PutTextR( "turbo", _pixDPWidth-1, _pixDPHeight-pixFontHeight*iLine, colCheat|ulAlpha); iLine++; } + if( cht_bInvisible) { _pDP->PutTextR( "invisible", _pixDPWidth-1, _pixDPHeight-pixFontHeight*iLine, colCheat|ulAlpha); iLine++; } + if( cht_bGhost) { _pDP->PutTextR( "ghost", _pixDPWidth-1, _pixDPHeight-pixFontHeight*iLine, colCheat|ulAlpha); iLine++; } + if( cht_bFly) { _pDP->PutTextR( "fly", _pixDPWidth-1, _pixDPHeight-pixFontHeight*iLine, colCheat|ulAlpha); iLine++; } + if( cht_bGod) { _pDP->PutTextR( "god", _pixDPWidth-1, _pixDPHeight-pixFontHeight*iLine, colCheat|ulAlpha); iLine++; } + } +} + + + +// initialized all whats need for drawing HUD +extern void InitHUD(void) +{ + // try to + try { + // initialize and load HUD numbers font + DECLARE_CTFILENAME( fnFont, "Fonts\\Numbers3.fnt"); + _fdNumbersFont.Load_t( fnFont); + //_fdNumbersFont.SetCharSpacing(0); + + // initialize status bar textures + _toHealth.SetData_t( CTFILENAME("Textures\\Interface\\HSuper.tex")); + _toArmor.SetData_t( CTFILENAME("Textures\\Interface\\ArStrong.tex")); + _toOxygen.SetData_t( CTFILENAME("Textures\\Interface\\Oxygen-2.tex")); + _toFrags.SetData_t( CTFILENAME("Textures\\Interface\\IBead.tex")); + _toDeaths.SetData_t( CTFILENAME("Textures\\Interface\\ISkull.tex")); + _toScore.SetData_t( CTFILENAME("Textures\\Interface\\IScore.tex")); + _toHiScore.SetData_t( CTFILENAME("Textures\\Interface\\IHiScore.tex")); + _toMessage.SetData_t( CTFILENAME("Textures\\Interface\\IMessage.tex")); + _toMana.SetData_t( CTFILENAME("Textures\\Interface\\IValue.tex")); + // initialize ammo textures + _toAShells.SetData_t( CTFILENAME("Textures\\Interface\\AmShells.tex")); + _toABullets.SetData_t( CTFILENAME("Textures\\Interface\\AmBullets.tex")); + _toARockets.SetData_t( CTFILENAME("Textures\\Interface\\AmRockets.tex")); + _toAGrenades.SetData_t( CTFILENAME("Textures\\Interface\\AmGrenades.tex")); + _toANapalm.SetData_t( CTFILENAME("Textures\\Interface\\AmFuelReservoir.tex")); + _toAElectricity.SetData_t( CTFILENAME("Textures\\Interface\\AmElectricity.tex")); + _toAIronBall.SetData_t( CTFILENAME("Textures\\Interface\\AmCannon.tex")); + // initialize weapon textures + _toWKnife.SetData_t( CTFILENAME("Textures\\Interface\\WKnife.tex")); + _toWColt.SetData_t( CTFILENAME("Textures\\Interface\\WColt.tex")); + _toWSingleShotgun.SetData_t( CTFILENAME("Textures\\Interface\\WSingleShotgun.tex")); + _toWDoubleShotgun.SetData_t( CTFILENAME("Textures\\Interface\\WDoubleShotgun.tex")); + _toWTommygun.SetData_t( CTFILENAME("Textures\\Interface\\WTommygun.tex")); + _toWMinigun.SetData_t( CTFILENAME("Textures\\Interface\\WMinigun.tex")); + _toWRocketLauncher.SetData_t( CTFILENAME("Textures\\Interface\\WRocketLauncher.tex")); + _toWGrenadeLauncher.SetData_t( CTFILENAME("Textures\\Interface\\WGrenadeLauncher.tex")); + _toWPipeBomb.SetData_t( CTFILENAME("Textures\\Interface\\WPipeBomb.tex")); + _toWFlamer.SetData_t( CTFILENAME("Textures\\Interface\\WFlamer.tex")); + _toWGhostBuster.SetData_t( CTFILENAME("Textures\\Interface\\WGhostBuster.tex")); + _toWLaser.SetData_t( CTFILENAME("Textures\\Interface\\WLaser.tex")); + _toWIronCannon.SetData_t( CTFILENAME("Textures\\Interface\\WCannon.tex")); + // initialize tile texture + _toTile.SetData_t( CTFILENAME("Textures\\Interface\\Tile.tex")); + + // set all textures as constant + ((CTextureData*)_toHealth .GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toArmor .GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toOxygen .GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toFrags .GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toDeaths .GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toScore .GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toHiScore.GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toMessage.GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toMana .GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toAShells .GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toABullets .GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toARockets .GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toAGrenades .GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toANapalm .GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toAElectricity.GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toAIronBall .GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toWKnife .GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toWColt .GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toWSingleShotgun .GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toWDoubleShotgun .GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toWTommygun .GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toWMinigun .GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toWRocketLauncher .GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toWGrenadeLauncher.GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toWPipeBomb .GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toWFlamer .GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toWGhostBuster .GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toWLaser .GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toWIronCannon .GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toTile .GetData())->Force(TEX_CONSTANT); + } + catch( char *strError) { + FatalError( strError); + } + +} + + +// clean up +extern void EndHUD(void) +{ + +} + diff --git a/Sources/Entities/Common/Particles.cpp b/Sources/Entities/Common/Particles.cpp index a7a956c..f46be6d 100644 --- a/Sources/Entities/Common/Particles.cpp +++ b/Sources/Entities/Common/Particles.cpp @@ -1,2988 +1,2984 @@ -#include "../StdH/StdH.h" -#include "Entities/BloodSpray.h" -#include "Entities/PlayerWeapons.h" -#include "Entities/WorldSettingsController.h" -#include "Entities/BackgroundViewer.h" - -static CTextureObject _toRomboidTrail; -static CTextureObject _toBombTrail; -static CTextureObject _toFirecrackerTrail; -static CTextureObject _toSpiralTrail; -static CTextureObject _toColoredStarsTrail; -static CTextureObject _toFireball01Trail; -static CTextureObject _toGrenadeTrail; -static CTextureObject _toCannonBall; -static CTextureObject _toRocketTrail; -static CTextureObject _toVerticalGradient; -static CTextureObject _toVerticalGradientAlpha; -static CTextureObject _toBlood01Trail; -static CTextureObject _toLavaTrailGradient; -static CTextureObject _toLavaTrailSmoke; -static CTextureObject _toFlamethrowerTrail; -static CTextureObject _toBoubble01; -static CTextureObject _toBoubble02; -static CTextureObject _toBoubble03; -static CTextureObject _toStar01; -static CTextureObject _toStar02; -static CTextureObject _toStar03; -static CTextureObject _toStar04; -static CTextureObject _toStar05; -static CTextureObject _toStar06; -static CTextureObject _toStar07; -static CTextureObject _toStar08; -static CTextureObject _toBlood; -static CTextureObject _toWaterfallGradient; -static CTextureObject _toGhostbusterBeam; -static CTextureObject _toLightning; -static CTextureObject _toSand; -static CTextureObject _toSandFlowGradient; -static CTextureObject _toWater; -static CTextureObject _toWaterFlowGradient; -static CTextureObject _toLava; -static CTextureObject _toLavaFlowGradient; -static CTextureObject _toBloodSprayTexture; -static CTextureObject _toFlowerSprayTexture; -static CTextureObject _toBonesSprayTexture; -static CTextureObject _toFeatherSprayTexture; -static CTextureObject _toStonesSprayTexture; -static CTextureObject _toLavaSprayTexture; -static CTextureObject _toBeastProjectileSprayTexture; -static CTextureObject _toLavaEruptingTexture; -static CTextureObject _toWoodSprayTexture; -static CTextureObject _toLavaBombTrailSmoke; -static CTextureObject _toLavaBombTrailGradient; -static CTextureObject _toElectricitySparks; -static CTextureObject _toBeastProjectileTrailTexture; -static CTextureObject _toBeastProjectileTrailGradient; -static CTextureObject _toBeastBigProjectileTrailTexture; -static CTextureObject _toBeastBigProjectileTrailGradient; -static CTextureObject _toBeastDebrisTrailGradient; -static CTextureObject _toBeastDebrisTrailTexture; -static CTextureObject _toRaindrop; -static CTextureObject _toSnowdrop; -static CTextureObject _toBulletStone; -static CTextureObject _toBulletSand; -static CTextureObject _toBulletSpark; -static CTextureObject _toBulletSmoke; -static CTextureObject _toBulletWater; -static CTextureObject _toPlayerParticles; -static CTextureObject _toWaterfallFoam; -static CTextureObject _toMetalSprayTexture; - -// array for model vertices in absolute space -CStaticStackArray avVertices; - -#define CT_MAX_PARTICLES_TABLE 512 - -FLOAT afTimeOffsets[CT_MAX_PARTICLES_TABLE]; -FLOAT afStarsPositions[CT_MAX_PARTICLES_TABLE][3]; -UBYTE auStarsColors[CT_MAX_PARTICLES_TABLE][3]; - -void InitParticleTables(void); - -// init particle effects -void InitParticles(void) -{ - try - { - _toRomboidTrail.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\Romboid.tex")); - _toBombTrail.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\WhiteBubble.tex")); - _toFirecrackerTrail.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\FireCracker.tex")); - _toSpiralTrail.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\Smoke01.tex")); - _toColoredStarsTrail.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\Star01.tex")); - _toFireball01Trail.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\Fireball01.tex")); - _toGrenadeTrail.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\Smoke02.tex")); - _toCannonBall.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\CannonBall.tex")); - _toRocketTrail.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\Smoke06.tex")); - _toVerticalGradient.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\VerticalGradient.tex")); - _toVerticalGradientAlpha.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\VerticalGradientAlpha.tex")); - _toBlood01Trail.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\Blood02.tex")); - _toLavaTrailGradient.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\LavaTrailGradient.tex")); - _toLavaTrailSmoke.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\LavaTrailSmoke.tex")); - _toFlamethrowerTrail.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\FlameThrower01.tex")); - _toBoubble01.SetData_t(CTFILENAME("Models\\Items\\Particles\\Boubble01.tex")); - _toBoubble02.SetData_t(CTFILENAME("Models\\Items\\Particles\\Boubble02.tex")); - _toBoubble03.SetData_t(CTFILENAME("Models\\Items\\Particles\\Boubble03.tex")); - _toStar01.SetData_t(CTFILENAME("Models\\Items\\Particles\\Star01.tex")); - _toStar02.SetData_t(CTFILENAME("Models\\Items\\Particles\\Star02.tex")); - _toStar03.SetData_t(CTFILENAME("Models\\Items\\Particles\\Star03.tex")); - _toStar04.SetData_t(CTFILENAME("Models\\Items\\Particles\\Star04.tex")); - _toStar05.SetData_t(CTFILENAME("Models\\Items\\Particles\\Star05.tex")); - _toStar06.SetData_t(CTFILENAME("Models\\Items\\Particles\\Star06.tex")); - _toStar07.SetData_t(CTFILENAME("Models\\Items\\Particles\\Star07.tex")); - _toStar08.SetData_t(CTFILENAME("Models\\Items\\Particles\\Star08.tex")); - _toWaterfallGradient.SetData_t(CTFILENAME("Models\\Effects\\Heatmaps\\Waterfall08.tex")); - _toGhostbusterBeam.SetData_t(CTFILENAME("Models\\Weapons\\GhostBuster\\Projectile\\Ray.tex")); - _toLightning.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\Lightning.tex")); - _toSand.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\Sand.tex")); - _toSandFlowGradient.SetData_t(CTFILENAME("Models\\Effects\\Heatmaps\\SandFlow01.tex")); - _toWater.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\Water.tex")); - _toWaterFlowGradient.SetData_t(CTFILENAME("Models\\Effects\\Heatmaps\\WaterFlow01.tex")); - _toLava.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\Lava.tex")); - _toLavaFlowGradient.SetData_t(CTFILENAME("Models\\Effects\\Heatmaps\\LavaFlow01.tex")); - _toBloodSprayTexture.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\Blood03.tex")); - _toFlowerSprayTexture.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\Flowers.tex")); - _toBonesSprayTexture.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\BonesSpill01.tex")); - _toFeatherSprayTexture.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\FeatherSpill01.tex")); - _toStonesSprayTexture.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\StonesSpill01.tex")); - _toLavaSprayTexture.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\LavaSpill01.tex")); - _toBeastProjectileSprayTexture.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\BeastProjectileSpill.tex")); - _toLavaEruptingTexture.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\LavaErupting.tex")); - _toWoodSprayTexture.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\WoodSpill01.tex")); - _toLavaBombTrailSmoke.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\LavaBomb.tex")); - _toLavaBombTrailGradient.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\LavaBombGradient.tex")); - _toBeastDebrisTrailGradient.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\BeastDebrisTrailGradient.tex")); - _toBeastProjectileTrailTexture.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\BeastProjectileTrail.tex")); - _toBeastProjectileTrailGradient.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\BeastProjectileTrailGradient.tex")); - _toBeastBigProjectileTrailTexture.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\BeastBigProjectileTrail.tex")); - _toBeastBigProjectileTrailGradient.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\BeastBigProjectileTrailGradient.tex")); - _toBeastDebrisTrailTexture.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\BeastDebrisTrail.tex")); - _toElectricitySparks.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\ElectricitySparks.tex")); - _toRaindrop.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\Raindrop.tex")); - _toSnowdrop.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\Snowdrop.tex")); - _toBulletStone.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\BulletSpray.tex")); - _toBulletWater.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\BulletSprayWater.tex")); - _toBulletSand.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\BulletSpraySand.tex")); - _toBulletSpark.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\BulletSpark.tex")); - _toBulletSmoke.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\SmokeAnim01.tex")); - _toPlayerParticles.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\PlayerParticles.tex")); - _toWaterfallFoam.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\WaterfallFoam.tex")); - _toMetalSprayTexture.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\MetalSpill.tex")); - - ((CTextureData*)_toLavaTrailGradient .GetData())->Force(TEX_STATIC); - ((CTextureData*)_toLavaBombTrailGradient .GetData())->Force(TEX_STATIC); - ((CTextureData*)_toBeastDebrisTrailGradient .GetData())->Force(TEX_STATIC); - ((CTextureData*)_toBeastProjectileTrailGradient .GetData())->Force(TEX_STATIC); - ((CTextureData*)_toBeastBigProjectileTrailGradient.GetData())->Force(TEX_STATIC); - ((CTextureData*)_toWaterfallGradient .GetData())->Force(TEX_STATIC); - ((CTextureData*)_toSandFlowGradient .GetData())->Force(TEX_STATIC); - ((CTextureData*)_toWaterFlowGradient .GetData())->Force(TEX_STATIC); - ((CTextureData*)_toLavaFlowGradient .GetData())->Force(TEX_STATIC); - } - catch(char *strError) - { - FatalError(TRANS("Unable to obtain texture: %s"), strError); - } - InitParticleTables(); -} - -// close particle effects -void CloseParticles(void) -{ - _toRomboidTrail.SetData(NULL); - _toBombTrail.SetData(NULL); - _toFirecrackerTrail.SetData(NULL); - _toSpiralTrail.SetData(NULL); - _toColoredStarsTrail.SetData(NULL); - _toFireball01Trail.SetData(NULL); - _toRocketTrail.SetData(NULL); - _toGrenadeTrail.SetData(NULL); - _toCannonBall.SetData(NULL); - _toVerticalGradient.SetData(NULL); - _toVerticalGradientAlpha.SetData(NULL); - _toBlood01Trail.SetData(NULL); - _toLavaTrailGradient.SetData(NULL); - _toWaterfallGradient.SetData(NULL); - _toGhostbusterBeam.SetData( NULL); - _toLightning.SetData( NULL); - _toLavaTrailSmoke.SetData(NULL); - _toFlamethrowerTrail.SetData(NULL); - _toBoubble01.SetData(NULL); - _toBoubble02.SetData(NULL); - _toBoubble03.SetData(NULL); - _toStar01.SetData(NULL); - _toStar02.SetData(NULL); - _toStar03.SetData(NULL); - _toStar04.SetData(NULL); - _toStar05.SetData(NULL); - _toStar06.SetData(NULL); - _toStar07.SetData(NULL); - _toStar08.SetData(NULL); - _toSand.SetData(NULL); - _toSandFlowGradient.SetData(NULL); - _toWater.SetData(NULL); - _toWaterFlowGradient.SetData(NULL); - _toLava.SetData(NULL); - _toLavaFlowGradient.SetData(NULL); - _toLavaBombTrailSmoke.SetData(NULL); - _toLavaBombTrailGradient.SetData(NULL); - _toBloodSprayTexture.SetData(NULL); - _toFlowerSprayTexture.SetData(NULL); - _toBonesSprayTexture.SetData(NULL); - _toFeatherSprayTexture.SetData(NULL); - _toStonesSprayTexture.SetData(NULL); - _toLavaSprayTexture.SetData(NULL); - _toBeastProjectileSprayTexture.SetData(NULL); - _toLavaEruptingTexture.SetData(NULL); - _toWoodSprayTexture.SetData(NULL); - _toElectricitySparks.SetData(NULL); - _toBeastDebrisTrailGradient.SetData(NULL); - _toBeastProjectileTrailTexture.SetData(NULL); - _toBeastProjectileTrailGradient.SetData(NULL); - _toBeastBigProjectileTrailTexture.SetData(NULL); - _toBeastBigProjectileTrailGradient.SetData(NULL); - _toBeastDebrisTrailTexture.SetData(NULL); - _toRaindrop.SetData(NULL); - _toSnowdrop.SetData(NULL); - _toBulletStone.SetData(NULL); - _toBulletWater.SetData(NULL); - _toBulletSand.SetData(NULL); - _toBulletSpark.SetData(NULL); - _toBulletSmoke.SetData(NULL); - _toPlayerParticles.SetData(NULL); - _toWaterfallFoam.SetData(NULL); - _toMetalSprayTexture.SetData(NULL); -} - -void Particles_ViewerLocal(CEntity *penView) -{ - ASSERT(penView!=NULL); - - // ----------- Obtain world settings controller - CWorldSettingsController *pwsc = NULL; - // obtain bcg viewer - CBackgroundViewer *penBcgViewer = (CBackgroundViewer *) penView->GetWorld()->GetBackgroundViewer(); - if( penBcgViewer != NULL) - { - // obtain world settings controller - pwsc = (CWorldSettingsController *) &*penBcgViewer->m_penWorldSettingsController; - } - - // ***** Storm appearing effects - // if world settings controller is valid - if( (pwsc != NULL) && (pwsc->m_tmStormStart != -1)) - { - FLOAT fStormFactor = pwsc->GetStormFactor(); - if( fStormFactor != 0.0f) - { - FLOATaabbox3D boxRainMap; - CTextureData *ptdRainMap; - pwsc->GetHeightMapData( ptdRainMap, boxRainMap); - Particles_Rain( penView, 1.25f, 32, fStormFactor, ptdRainMap, boxRainMap); - } - } -} - -// different particle effects -#define ROMBOID_TRAIL_POSITIONS 16 -void Particles_RomboidTrail(CEntity *pen) -{ - CLastPositions *plp = pen->GetLastPositions(ROMBOID_TRAIL_POSITIONS); - FLOAT fSeconds = _pTimer->GetLerpedCurrentTick(); - - Particle_PrepareTexture(&_toRomboidTrail, PBT_ADD); - Particle_SetTexturePart( 512, 512, 0, 0); - - for(INDEX iPos = 0; iPoslp_ctUsed; iPos++) - { - FLOAT3D vPos = plp->GetPosition(iPos); - //FLOAT fRand = rand()/FLOAT(RAND_MAX); - FLOAT fAngle = fSeconds*256+iPos*2.0f*PI/ROMBOID_TRAIL_POSITIONS; - FLOAT fSin = FLOAT(sin(fAngle)); - vPos(2) += fSin*iPos/ROMBOID_TRAIL_POSITIONS; - FLOAT fSize = (ROMBOID_TRAIL_POSITIONS-iPos)*0.5f/ROMBOID_TRAIL_POSITIONS+0.1f; - UBYTE ub = 255-iPos*255/ROMBOID_TRAIL_POSITIONS; - Particle_RenderSquare( vPos, fSize, fAngle, RGBToColor(255-ub,ub,255-ub)|ub); - } - // all done - Particle_Flush(); -} - -#define BOMB_TRAIL_POSITIONS 8 -#define BOMB_TRAIL_INTERPOSITIONS 4 -void Particles_BombTrail_Prepare(CEntity *pen) -{ - pen->GetLastPositions(BOMB_TRAIL_POSITIONS); -} -void Particles_BombTrail(CEntity *pen) -{ - CLastPositions *plp = pen->GetLastPositions(BOMB_TRAIL_POSITIONS); - - Particle_PrepareTexture(&_toBombTrail, PBT_ADD); - Particle_SetTexturePart( 512, 512, 0, 0); - - const FLOAT3D *pvPos1; - const FLOAT3D *pvPos2 = &plp->GetPosition(plp->lp_ctUsed-1); - for(INDEX iPos = plp->lp_ctUsed-1; iPos>=1; iPos--) - { - pvPos1 = pvPos2; - pvPos2 = &plp->GetPosition(iPos); - for (INDEX iInter=0; iInterGetLastPositions(FIRECRACKER_TRAIL_POSITIONS); -} -void Particles_FirecrackerTrail(CEntity *pen) -{ - CLastPositions *plp = pen->GetLastPositions(FIRECRACKER_TRAIL_POSITIONS); - Particle_PrepareTexture(&_toFirecrackerTrail, PBT_ADD); - Particle_SetTexturePart( 512, 512, 0, 0); - - if( plp->lp_ctUsed<2) return; - const FLOAT3D *pvPos1; - const FLOAT3D *pvPos2 = &plp->GetPosition(plp->lp_ctUsed-1); - INDEX iParticle = plp->lp_ctUsed*FIRECRACKER_TRAIL_INTERPOSITIONS; - for(INDEX iPos = plp->lp_ctUsed-2; iPos>=0; iPos--) - { - pvPos1 = pvPos2; - pvPos2 = &plp->GetPosition(iPos); - for (INDEX iInter=0; iInterGetLastPositions(SPIRAL_TRAIL_POSITIONS); - - FLOAT fSeconds = _pTimer->GetLerpedCurrentTick(); - Particle_PrepareTexture(&_toSpiralTrail, PBT_ADD); - Particle_SetTexturePart( 512, 512, 0, 0); - - for(INDEX iPos = 0; iPoslp_ctUsed; iPos++) - { - FLOAT3D vPos = plp->GetPosition(iPos); - FLOAT fAngle = fSeconds*32.0f+iPos*2*PI/SPIRAL_TRAIL_POSITIONS; - FLOAT fSin = FLOAT(sin(fAngle)); - FLOAT fCos = FLOAT(cos(fAngle)); - - vPos(1) += fSin*iPos*1.0f/SPIRAL_TRAIL_POSITIONS; - vPos(2) += fCos*iPos*1.0f/SPIRAL_TRAIL_POSITIONS; - - UBYTE ub = iPos*SPIRAL_TRAIL_POSITIONS; - Particle_RenderSquare( vPos, 0.2f, fAngle, RGBToColor(ub,ub,ub)|ub); - } - // all done - Particle_Flush(); -} - -static COLOR _aColors[] = { C_WHITE, C_GRAY, - C_RED, C_GREEN, C_BLUE, C_CYAN, C_MAGENTA, C_YELLOW, C_ORANGE, C_BROWN, C_PINK, - C_lRED, C_lGREEN, C_lBLUE, C_lCYAN, C_lMAGENTA, C_lYELLOW, C_lORANGE, C_lBROWN, C_lPINK -}; - -#define COLORED_STARS_TRAIL_POSITIONS 16 -void Particles_ColoredStarsTrail(CEntity *pen) -{ - CLastPositions *plp = pen->GetLastPositions(COLORED_STARS_TRAIL_POSITIONS); - FLOAT fSeconds = _pTimer->GetLerpedCurrentTick(); - - Particle_PrepareTexture(&_toColoredStarsTrail, PBT_ADD); - Particle_SetTexturePart( 512, 512, 0, 0); - - for(INDEX iPos = 0; iPoslp_ctUsed; iPos++) - { - FLOAT3D vPos1 = plp->GetPosition(iPos); - //FLOAT3D vPos2 = vPos1; - - FLOAT fAngle = fSeconds*64.0f+iPos*2*PI/COLORED_STARS_TRAIL_POSITIONS; - FLOAT fSin = FLOAT(sin(fAngle)); - //FLOAT fCos = FLOAT(cos(fAngle)); - - FLOAT fDeltaY = fSin/2.0f; - vPos1(2) += fDeltaY; - //vPos2(2) -= fDeltaY; - - FLOAT fRand = rand()/FLOAT(RAND_MAX); - INDEX iRandColor = INDEX(fRand*sizeof(_aColors)/sizeof(COLOR)); - COLOR colColor1 = _aColors[ iRandColor]; - Particle_RenderSquare( vPos1, 0.4f, fAngle, colColor1); - } - // all done - Particle_Flush(); -} - -#define WHITE_LINE_TRAIL_POSITIONS 8 -void Particles_WhiteLineTrail(CEntity *pen) -{ - CLastPositions *plp = pen->GetLastPositions(WHITE_LINE_TRAIL_POSITIONS); - FLOAT fSeconds = _pTimer->GetLerpedCurrentTick(); - - Particle_PrepareTexture(&_toSpiralTrail, PBT_ADD); - Particle_SetTexturePart( 1, 1, 256, 256); - - FLOAT3D vOldPos = plp->GetPosition(0); - for(INDEX iPos = 1; iPoslp_ctUsed; iPos++) - { - FLOAT3D vPos = plp->GetPosition(iPos); - FLOAT fAngle = fSeconds*4.0f+iPos*PI/WHITE_LINE_TRAIL_POSITIONS; - FLOAT fSin = FLOAT(sin(fAngle)); - FLOAT fCos = FLOAT(cos(fAngle)); - - vPos(1) += fSin*iPos*1.0f/WHITE_LINE_TRAIL_POSITIONS; - vPos(2) += fCos*iPos*1.0f/WHITE_LINE_TRAIL_POSITIONS; - - //UBYTE ub = 255-iPos*256/WHITE_LINE_TRAIL_POSITIONS; - FLOAT fLerpFactor = FLOAT(iPos)/WHITE_LINE_TRAIL_POSITIONS; - COLOR colColor = LerpColor( C_YELLOW, C_dRED, fLerpFactor); - Particle_RenderLine( vPos, vOldPos, 0.05f, colColor); - vOldPos =vPos; - } - // all done - Particle_Flush(); -} - - -#define FIREBALL01_TRAIL_POSITIONS 8 -#define FIREBALL01_TRAIL_INTERPOSITIONS 4 -#define FIREBALL01_TRAIL_PARTICLES (FIREBALL01_TRAIL_INTERPOSITIONS*FIREBALL01_TRAIL_POSITIONS) -void Particles_Fireball01Trail_Prepare(CEntity *pen) -{ - pen->GetLastPositions(FIREBALL01_TRAIL_POSITIONS); -} -void Particles_Fireball01Trail(CEntity *pen) -{ - CLastPositions *plp = pen->GetLastPositions(FIREBALL01_TRAIL_POSITIONS); - Particle_PrepareTexture(&_toFireball01Trail, PBT_ADD); - Particle_SetTexturePart( 512, 512, 0, 0); - - const FLOAT3D *pvPos1; - const FLOAT3D *pvPos2 = &plp->GetPosition(plp->lp_ctUsed-1); - INDEX iParticle = 0; - INDEX iParticlesLiving = plp->lp_ctUsed*FIREBALL01_TRAIL_INTERPOSITIONS; - for(INDEX iPos = plp->lp_ctUsed-2; iPos>=0; iPos--) { - pvPos1 = pvPos2; - pvPos2 = &plp->GetPosition(iPos); - COLOR colColor; - for (INDEX iInter=0; iInterGetLastPositions(GRENADE_TRAIL_POSITIONS); -} -void Particles_GrenadeTrail(CEntity *pen) -{ - CLastPositions *plp = pen->GetLastPositions(GRENADE_TRAIL_POSITIONS); - FLOAT fSeconds = _pTimer->GetLerpedCurrentTick(); - - Particle_PrepareTexture(&_toGrenadeTrail, PBT_MULTIPLY); - Particle_SetTexturePart( 512, 512, 0, 0); - - const FLOAT3D *pvPos1; - const FLOAT3D *pvPos2 = &plp->GetPosition(0); - INDEX iParticle = 0; - INDEX iParticlesLiving = plp->lp_ctUsed*GRENADE_TRAIL_INTERPOSITIONS; - for(INDEX iPos = 1; iPoslp_ctUsed; iPos++) - { - pvPos1 = pvPos2; - pvPos2 = &plp->GetPosition(iPos); - for (INDEX iInter=0; iInterGetLastPositions(CANNON_TRAIL_POSITIONS); -} -void Particles_CannonBall(CEntity *pen, FLOAT fSpeedRatio) -{ - CLastPositions *plp = pen->GetLastPositions(CANNON_TRAIL_POSITIONS); - // FLOAT fSeconds = _pTimer->GetLerpedCurrentTick(); - - Particle_PrepareTexture(&_toCannonBall, PBT_BLEND); - Particle_SetTexturePart( 512, 512, 0, 0); - - FLOAT3D vOldPos = plp->GetPosition(1); - for( INDEX iPos=2; iPoslp_ctUsed; iPos++) - { - FLOAT3D vPos = plp->GetPosition(iPos); - UBYTE ub = UBYTE((255-iPos*256/plp->lp_ctUsed)*fSpeedRatio); - FLOAT fSize = (CANNON_TRAIL_POSITIONS-iPos)*0.04f+0.04f; - Particle_RenderLine( vPos, vOldPos, fSize, RGBToColor(ub,ub,ub)|ub); - vOldPos=vPos; - } - // all done - Particle_Flush(); -} - -#define LAVA_TRAIL_POSITIONS 32 -#define LAVA_TRAIL_INTERPOSITIONS 1 -void Particles_LavaTrail_Prepare(CEntity *pen) -{ - pen->GetLastPositions(LAVA_TRAIL_POSITIONS); -} -void Particles_LavaTrail(CEntity *pen) -{ - CLastPositions *plp = pen->GetLastPositions(LAVA_TRAIL_POSITIONS); - FLOAT fSeconds = _pTimer->GetLerpedCurrentTick(); - - CTextureData *pTD = (CTextureData *) _toLavaTrailGradient.GetData(); - Particle_PrepareTexture(&_toLavaTrailSmoke, PBT_BLEND); - //Particle_PrepareTexture(&_toLavaTrailSmoke, PBT_MULTIPLY); - Particle_SetTexturePart( 512, 512, 0, 0); - - const FLOAT3D *pvPos1; - const FLOAT3D *pvPos2 = &plp->GetPosition(0); - INDEX iParticle = 0; - INDEX iParticlesLiving = plp->lp_ctUsed*LAVA_TRAIL_INTERPOSITIONS; - for(INDEX iPos = 1; iPoslp_ctUsed; iPos++) - { - pvPos1 = pvPos2; - pvPos2 = &plp->GetPosition(iPos); - for (INDEX iInter=0; iInterGetTexel(PIX(FLOAT(iParticle)/iParticlesLiving*8*1024), 0); - Particle_RenderSquare( vPos, fSize, fAngle, col); - iParticle++; - } - } - // all done - Particle_Flush(); -} - -#define LAVA_BOMB_TRAIL_POSITIONS 16 -#define LAVA_BOMB_TRAIL_INTERPOSITIONS 1 -void Particles_LavaBombTrail_Prepare(CEntity *pen) -{ - pen->GetLastPositions(LAVA_BOMB_TRAIL_POSITIONS); -} - -void Particles_LavaBombTrail(CEntity *pen, FLOAT fSizeMultiplier) -{ - CLastPositions *plp = pen->GetLastPositions(LAVA_BOMB_TRAIL_POSITIONS); - FLOAT fSeconds = _pTimer->GetLerpedCurrentTick(); - - CTextureData *pTD = (CTextureData *) _toLavaBombTrailGradient.GetData(); - Particle_PrepareTexture(&_toLavaBombTrailSmoke, PBT_BLEND); - Particle_SetTexturePart( 512, 512, 0, 0); - - const FLOAT3D *pvPos1; - const FLOAT3D *pvPos2 = &plp->GetPosition(0); - INDEX iParticle = 0; - INDEX iParticlesLiving = plp->lp_ctUsed*LAVA_BOMB_TRAIL_INTERPOSITIONS; - for(INDEX iPos = 1; iPoslp_ctUsed; iPos++) - { - INDEX iRnd = ((ULONG)fSeconds+iPos)%CT_MAX_PARTICLES_TABLE; - pvPos1 = pvPos2; - pvPos2 = &plp->GetPosition(iPos); - if( *pvPos1 == *pvPos2) continue; - for (INDEX iInter=0; iInterGetTexel(PIX(FLOAT(iParticle)/iParticlesLiving*8*1024), 0); - Particle_RenderSquare( vPos, fSize, fAngle, col); - iParticle++; - } - } - // all done - Particle_Flush(); -} - -#define BEAST_PROJECTILE_DEBRIS_TRAIL_POSITIONS 8 -#define BEAST_PROJECTILE_DEBRIS_TRAIL_INTERPOSITIONS 1 -void Particles_BeastProjectileDebrisTrail_Prepare(CEntity *pen) -{ - pen->GetLastPositions(BEAST_PROJECTILE_DEBRIS_TRAIL_POSITIONS); -} - -void Particles_BeastProjectileDebrisTrail(CEntity *pen, FLOAT fSizeMultiplier) -{ - CLastPositions *plp = pen->GetLastPositions(BEAST_PROJECTILE_DEBRIS_TRAIL_POSITIONS); - FLOAT fSeconds = _pTimer->GetLerpedCurrentTick(); - - CTextureData *pTD = (CTextureData *) _toBeastDebrisTrailGradient.GetData(); - Particle_PrepareTexture(&_toBeastDebrisTrailTexture, PBT_BLEND); - Particle_SetTexturePart( 512, 512, 0, 0); - - const FLOAT3D *pvPos1; - const FLOAT3D *pvPos2 = &plp->GetPosition(0); - INDEX iParticle = 0; - INDEX iParticlesLiving = plp->lp_ctUsed*BEAST_PROJECTILE_DEBRIS_TRAIL_INTERPOSITIONS; - for(INDEX iPos = 1; iPoslp_ctUsed; iPos++) - { - pvPos1 = pvPos2; - pvPos2 = &plp->GetPosition(iPos); - for (INDEX iInter=0; iInterGetTexel(PIX(FLOAT(iParticle)/iParticlesLiving*8*1024), 0); - Particle_RenderSquare( vPos, fSize, fAngle, col); - iParticle++; - } - } - // all done - Particle_Flush(); -} - -#define BEAST_PROJECTILE_TRAIL_POSITIONS 32 -#define BEAST_PROJECTILE_TRAIL_INTERPOSITIONS 1 -void Particles_BeastProjectileTrail_Prepare(CEntity *pen) -{ - pen->GetLastPositions(BEAST_PROJECTILE_TRAIL_POSITIONS); -} - -#define BEAST_PROJECTILE_LINE_PARTICLES 0.4f -#define BEAST_PROJECTILE_FADE_OUT 0.3f -#define BEAST_PROJECTILE_TOTAL_TIME 0.6f -void Particles_BeastProjectileTrail( CEntity *pen, FLOAT fSize, FLOAT fHeight, INDEX ctParticles) -{ - ASSERT( ctParticles<=CT_MAX_PARTICLES_TABLE); - FLOAT fNow = _pTimer->GetLerpedCurrentTick(); - - Particle_PrepareTexture(&_toBeastProjectileTrailTexture, PBT_BLEND); - Particle_SetTexturePart( 512, 2048, 0, 0); - - CTextureData *pTD = (CTextureData *) _toBeastProjectileTrailGradient.GetData(); - - CPlacement3D pl = pen->GetLerpedPlacement(); - FLOATmatrix3D m; - MakeRotationMatrixFast(m, pl.pl_OrientationAngle); - FLOAT3D vX( m(1,1), m(2,1), m(3,1)); - FLOAT3D vY( -m(1,3), -m(2,3), -m(3,3)); - FLOAT3D vZ( m(1,2), m(2,2), m(3,2)); - FLOAT3D vCenter = pl.pl_PositionVector+vY*fHeight; - - for( INDEX iStar=0; iStar(1.0f-BEAST_PROJECTILE_FADE_OUT)) fFade=(1-fT)*(1/BEAST_PROJECTILE_FADE_OUT); - //else fFade=1.0f; - -#define GET_POS( time) vCenter + \ - vX*(afStarsPositions[iStar][0]*time*fSize*1.5) +\ - vY*(-time*time*10.0f+(afStarsPositions[iStar][1]*2+2.0f)*1.2f*time) +\ - vZ*(afStarsPositions[iStar][2]*time*fSize*1.5); - - FLOAT3D vPos = GET_POS( fT); - COLOR colStar = pTD->GetTexel( FloatToInt(fT*8192), 0); - - if( fT>BEAST_PROJECTILE_LINE_PARTICLES) - { - FLOAT fTimeOld = fT-0.25f; - FLOAT3D vOldPos = GET_POS( fTimeOld); - Particle_RenderLine( vOldPos, vPos, 0.4f, colStar); - } - else - { - Particle_RenderSquare( vPos, 0.5f, fT*360.0f, colStar); - } - } - // all done - Particle_Flush(); -} - -#define BEAST_BIG_PROJECTILE_TRAIL_POSITIONS 32 -#define BEAST_BIG_PROJECTILE_TRAIL_INTERPOSITIONS 1 -void Particles_BeastBigProjectileTrail_Prepare(CEntity *pen) -{ - pen->GetLastPositions(BEAST_BIG_PROJECTILE_TRAIL_POSITIONS); -} - -#define BIG_BEAST_PROJECTILE_LINE_PARTICLES 0.4f -#define BIG_BEAST_PROJECTILE_FADE_OUT 0.4f -#define BIG_BEAST_PROJECTILE_TOTAL_TIME 0.6f -void Particles_BeastBigProjectileTrail( CEntity *pen, FLOAT fSize, FLOAT fZOffset, FLOAT fYOffset, INDEX ctParticles) -{ - ASSERT( ctParticles<=CT_MAX_PARTICLES_TABLE); - FLOAT fNow = _pTimer->GetLerpedCurrentTick(); - - Particle_PrepareTexture(&_toBeastBigProjectileTrailTexture, PBT_BLEND); - Particle_SetTexturePart( 512, 2048, 0, 0); - - CTextureData *pTD = (CTextureData *) _toBeastBigProjectileTrailGradient.GetData(); - - CPlacement3D pl = pen->GetLerpedPlacement(); - FLOATmatrix3D m; - MakeRotationMatrixFast(m, pl.pl_OrientationAngle); - FLOAT3D vX( m(1,1), m(2,1), m(3,1)); - FLOAT3D vY( -m(1,3), -m(2,3), -m(3,3)); - FLOAT3D vZ( m(1,2), m(2,2), m(3,2)); - FLOAT3D vCenter = pl.pl_PositionVector+vY*fZOffset+vZ*fYOffset; - - for( INDEX iStar=0; iStar(1.0f-BIG_BEAST_PROJECTILE_FADE_OUT)) fFade=(1-fT)*(1/BIG_BEAST_PROJECTILE_FADE_OUT); - else fFade=1.0f; - -#define GET_POS_BIG( time) vCenter + \ - vX*(afStarsPositions[iStar][0]*time*fSize*1.5) +\ - vY*(time*time*-15.0f+(afStarsPositions[iStar][1]*2+3.0f)*1.2f*time) +\ - vZ*(afStarsPositions[iStar][2]*time*fSize*1.5); - - FLOAT3D vPos = GET_POS_BIG( fT); - COLOR colStar = pTD->GetTexel( FloatToInt(fT*8192), 0); - - if( fT>BIG_BEAST_PROJECTILE_LINE_PARTICLES) - { - FLOAT fTimeOld = fT-0.125f; - FLOAT3D vOldPos = GET_POS_BIG( fTimeOld); - Particle_RenderLine( vOldPos, vPos, 0.6f*fFade, colStar); - } - else - { - Particle_RenderSquare( vPos, 0.5, fT*360.0f, colStar); - } - } - // all done - Particle_Flush(); -} - -#define ROCKET_TRAIL_POSITIONS 16 -#define ROCKET_TRAIL_INTERPOSITIONS 3 -void Particles_RocketTrail_Prepare(CEntity *pen) -{ - pen->GetLastPositions(ROCKET_TRAIL_POSITIONS); -} -void Particles_RocketTrail(CEntity *pen, FLOAT fStretch) -{ - CLastPositions *plp = pen->GetLastPositions(ROCKET_TRAIL_POSITIONS); - //FLOAT fSeconds = _pTimer->GetLerpedCurrentTick(); - - Particle_PrepareTexture(&_toRocketTrail, PBT_ADD); - Particle_SetTexturePart( 512, 512, 0, 0); - - const FLOAT3D *pvPos1; - const FLOAT3D *pvPos2 = &plp->GetPosition(1); - INDEX iParticle = 0; - INDEX iParticlesLiving = plp->lp_ctUsed*ROCKET_TRAIL_INTERPOSITIONS; - for( INDEX iPos=2; iPoslp_ctUsed; iPos++) - { - pvPos1 = pvPos2; - pvPos2 = &plp->GetPosition(iPos); - if( (*pvPos2 - *pvPos1).Length() == 0.0f) - { - continue; - } - for (INDEX iInter=0; iInterGetPosition(1); - for( INDEX iPos=2; iPoslp_ctUsed; iPos++) - { - FLOAT3D vPos = plp->GetPosition(iPos); - if( (vPos - vOldPos).Length() == 0.0f) - { - continue; - } - UBYTE ub = UBYTE(255-iPos*256/plp->lp_ctUsed); - FLOAT fSize = iPos*0.01f*fStretch+0.005f; - Particle_RenderLine( vPos, vOldPos, fSize, RGBToColor(ub,ub,ub)|ub); - vOldPos=vPos; - } - // all done - Particle_Flush(); -} - - -#define BLOOD01_TRAIL_POSITIONS 15 -void Particles_BloodTrail(CEntity *pen) -{ - // get blood type - const INDEX iBloodType = GetSP()->sp_iBlood; - if( iBloodType<1) return; - COLOR col; - if( iBloodType==3) Particle_PrepareTexture( &_toFlowerSprayTexture, PBT_BLEND); - else Particle_PrepareTexture( &_toBloodSprayTexture, PBT_BLEND); - - CLastPositions *plp = pen->GetLastPositions(BLOOD01_TRAIL_POSITIONS); - FLOAT fGA = ((CMovableEntity *)pen)->en_fGravityA; - FLOAT3D vGDir = ((CMovableEntity *)pen)->en_vGravityDir; - - for( INDEX iPos=0; iPoslp_ctUsed; iPos++) - { - Particle_SetTexturePart( 256, 256, iPos%8, 0); - FLOAT3D vPos = plp->GetPosition(iPos); - //FLOAT fRand = rand()/FLOAT(RAND_MAX); - FLOAT fAngle = iPos*2.0f*PI/BLOOD01_TRAIL_POSITIONS; - //FLOAT fSin = FLOAT(sin(fAngle)); - FLOAT fT = iPos*_pTimer->TickQuantum; - vPos += vGDir*fGA*fT*fT/8.0f; - FLOAT fSize = 0.2f-iPos*0.15f/BLOOD01_TRAIL_POSITIONS; - UBYTE ub = 255-iPos*255/BLOOD01_TRAIL_POSITIONS; - if( iBloodType==3) col = C_WHITE|ub; - else if( iBloodType==2) col = RGBAToColor(ub,20,20,ub); - else col = RGBAToColor(0,ub,0,ub); - Particle_RenderSquare( vPos, fSize, fAngle, col); - } - // all done - Particle_Flush(); -} - - -INDEX Particles_FireBreath(CEntity *pen, FLOAT3D vSource, FLOAT3D vTarget, FLOAT tmStart, FLOAT tmStop) -{ - Particle_PrepareTexture( &_toFlamethrowerTrail, PBT_ADD); - Particle_SetTexturePart( 512, 512, 0, 0); - - FLOAT fNow = _pTimer->GetLerpedCurrentTick(); - FLOAT fFlameLife = 2; - INDEX ctFlames = 32; - INDEX ctRendered = 0; - FLOAT tmFlameDelta = 0.25f; - FLOAT3D vFocus = Lerp( vSource, vTarget, 0.25f); - for( INDEX iFlame=0; iFlamefFlameLife || tmFakeStart>tmStop) continue; - // calculate fraction part - FLOAT fT=fPassedTime/fFlameLife; - fT=fT-INDEX(fT); - // lerp position - FLOAT3D vRnd = FLOAT3D( afStarsPositions[iFlame][0],afStarsPositions[iFlame][1], - afStarsPositions[iFlame][2])*10; - FLOAT3D vPos = Lerp( vSource, vFocus+vRnd, fT); - FLOAT fSize = 5.0f*fT+5.0f; - UBYTE ub = CalculateRatio( fT, 0.0f, 1.0f, 0.1f, 0.2f)*255; - Particle_RenderSquare( vPos, fSize, fT*(1.0f+afStarsPositions[iFlame*3][1])*360.0f, RGBToColor(ub,ub,ub)|0xFF); - ctRendered++; - } - // all done - Particle_Flush(); - return ctRendered; -} - -INDEX Particles_Regeneration(CEntity *pen, FLOAT tmStart, FLOAT tmStop, FLOAT fYFactor, BOOL bDeath) -{ - Particle_PrepareTexture( &_toElectricitySparks, PBT_BLEND); - Particle_SetTexturePart( 512, 1024, 0, 0); - FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector; - - FLOAT fNow = _pTimer->GetLerpedCurrentTick(); - FLOAT fLife = 1.5; - INDEX ctRendered = 0; - FLOAT tmDelta = 0.001f; - for( INDEX iVtx=0; iVtx<1024*4; iVtx++) - { - FLOAT tmFakeStart = tmStart+iVtx*tmDelta; - FLOAT fPassedTime = fNow-tmFakeStart; - if(fPassedTime<0.0f || fPassedTime>fLife || tmFakeStart>tmStop) continue; - // calculate fraction part - FLOAT fT=fPassedTime/fLife; - fT=fT-INDEX(fT); - - INDEX iRnd = iVtx%CT_MAX_PARTICLES_TABLE; - FLOAT3D vRnd= FLOAT3D(afStarsPositions[iRnd][0],afStarsPositions[iRnd][1]+0.5f,afStarsPositions[iRnd][2]); - vRnd(1) *= 800.0f; - vRnd(2) *= 400.0f; - vRnd(3) *= 800.0f; - FLOAT3D vSource = vCenter+vRnd; - FLOAT3D vDestination = vCenter+vRnd*0.05f; - vDestination(2) += 40.0f*fYFactor+vRnd(2)/8.0f*fYFactor; - FLOAT3D vPos, vPos2; - // lerp position - if(bDeath) { - vPos = Lerp( vSource, vDestination, 1.0f-fT); - } else { - vPos = Lerp( vSource, vDestination, fT); - } - FLOAT fT2 = Clamp(fT-0.025f-fT*fT*0.025f, 0.0f, 1.0f); - - if(bDeath) { - vPos2 = Lerp( vSource, vDestination, 1.0f-fT2); - } else { - vPos2 = Lerp( vSource, vDestination, fT2); - } - - UBYTE ubR = 192+afStarsPositions[iRnd][0]*64; - UBYTE ubG = 192+afStarsPositions[iRnd][1]*64; - UBYTE ubB = 192+afStarsPositions[iRnd][2]*64; - UBYTE ubA = CalculateRatio( fT, 0.0f, 1.0f, 0.4f, 0.01f)*255; - COLOR colLine = RGBToColor( ubR, ubG, ubB) | ubA; - - FLOAT fSize = 1.0f; - Particle_RenderLine( vPos2, vPos, fSize, colLine); - ctRendered++; - } - - // flush array - avVertices.PopAll(); - // all done - Particle_Flush(); - return ctRendered; -} - -#define SECONDS_PER_PARTICLE 0.01f -void Particles_FlameThrower(const CPlacement3D &plEnd, const CPlacement3D &plStart, - FLOAT fEndElapsed, FLOAT fStartElapsed) -{ - Particle_PrepareTexture( &_toFlamethrowerTrail, PBT_ADD); - Particle_SetTexturePart( 512, 512, 0, 0); - - const FLOAT3D &vStart = plStart.pl_PositionVector; - const FLOAT3D &vEnd = plEnd.pl_PositionVector; - FLOAT3D vDelta = (vEnd-vStart)/(fEndElapsed-fStartElapsed); - FLOAT fSeconds = _pTimer->GetLerpedCurrentTick(); - - for(FLOAT fTime = ceil(fStartElapsed/SECONDS_PER_PARTICLE)*SECONDS_PER_PARTICLE; - fTime0.75f) ub = 0; - else if( fTime>0.5f) ub = (-4*fTime+3)*96; - - ASSERT(fTime>=0.0f); - ASSERT(fSize>=0.0f); - FLOAT3D vPos = vStart+vDelta*(fTime-fStartElapsed)+FLOAT3D(0.0f, fRise, 0.0f); - Particle_RenderSquare( vPos, fSize, fAngle, RGBToColor(ub,ub,ub)|0xFF); - } - // all done - Particle_Flush(); -} - -void SetupParticleTexture(enum ParticleTexture ptTexture) -{ - switch(ptTexture) { - case PT_STAR01: Particle_PrepareTexture(&_toStar01, PBT_ADD); break; - case PT_STAR02: Particle_PrepareTexture(&_toStar02, PBT_ADD); break; - case PT_STAR03: Particle_PrepareTexture(&_toStar03, PBT_ADD); break; - case PT_STAR04: Particle_PrepareTexture(&_toStar04, PBT_ADD); break; - case PT_STAR05: Particle_PrepareTexture(&_toStar05, PBT_ADD); break; - case PT_STAR06: Particle_PrepareTexture(&_toStar06, PBT_ADD); break; - case PT_STAR07: Particle_PrepareTexture(&_toStar07, PBT_ADD); break; - case PT_STAR08: Particle_PrepareTexture(&_toStar08, PBT_ADD); break; - case PT_BOUBBLE01: Particle_PrepareTexture(&_toBoubble01, PBT_ADD); break; - case PT_BOUBBLE02: Particle_PrepareTexture(&_toBoubble02, PBT_ADD); break; - case PT_WATER01: Particle_PrepareTexture(&_toBoubble03, PBT_BLEND); break; - case PT_WATER02: Particle_PrepareTexture(&_toBoubble03, PBT_BLEND); break; - case PT_SANDFLOW: Particle_PrepareTexture(&_toSand, PBT_BLEND); break; - case PT_WATERFLOW: Particle_PrepareTexture(&_toWater, PBT_BLEND); break; - case PT_LAVAFLOW: Particle_PrepareTexture(&_toLava, PBT_BLEND); break; - default: ASSERT(FALSE); - } - Particle_SetTexturePart( 512, 512, 0, 0); -} - -void InitParticleTables(void) -{ - for( INDEX iStar=0; iStar7.0f) return; - - FLOAT fNow = _pTimer->GetLerpedCurrentTick(); - SetupParticleTexture( ptTexture); - const FLOATmatrix3D &m = pen->GetRotationMatrix(); - FLOAT3D vY( m(1,2), m(2,2), m(3,2)); - CPlacement3D plSource = pen->GetLerpedPlacement(); - FLOAT3D vCenter = plSource.pl_PositionVector+vY*fHeight; - - for( INDEX iStar=0; iStarSTARDUST_EXIST_TIME) continue; - FLOAT fFade = -2.0f * Abs(fT*(1.0f/STARDUST_EXIST_TIME)-0.5f)+1.0f; - - INDEX iRandomFromPlacement = - (ULONG)(plSource.pl_PositionVector(1)+plSource.pl_PositionVector(3))&(ctOffsetSpace-1); - INDEX iMemeber = iStar+iRandomFromPlacement; - const FLOAT3D vPos = vCenter+FLOAT3D( afStarsPositions[iMemeber][0], - afStarsPositions[iMemeber][1], - afStarsPositions[iMemeber][2])*fSize; - COLOR colStar = RGBToColor( auStarsColors[iMemeber][0]*fFade, - auStarsColors[iMemeber][1]*fFade, - auStarsColors[iMemeber][2]*fFade); - Particle_RenderSquare( vPos, 0.15f, 0, colStar|0xFF); - } - // all done - Particle_Flush(); -} - -#define RISING_TOTAL_TIME 5.0f -#define RISING_EXIST_TIME 3.0f -#define RISING_FADE_IN 0.3f -#define RISING_FADE_OUT 0.3f - -void Particles_Rising(CEntity *pen, FLOAT fStartTime, FLOAT fStopTime, FLOAT fStretchAll, - FLOAT fStretchX, FLOAT fStretchY, FLOAT fStretchZ, FLOAT fSize, - enum ParticleTexture ptTexture, INDEX ctParticles) -{ - ASSERT( ctParticles<=CT_MAX_PARTICLES_TABLE); - if( Particle_GetMipFactor()>7.0f) return; - - FLOAT fNow = _pTimer->GetLerpedCurrentTick(); - SetupParticleTexture( ptTexture); - const FLOATmatrix3D &m = pen->GetRotationMatrix(); - FLOAT3D vY( m(1,2), m(2,2), m(3,2)); - FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector+vY*fStretchY; - - FLOAT fPowerFactor = Clamp((fNow - fStartTime)/5.0f,0.0f,1.0f); - fPowerFactor *= Clamp(1+(fStopTime-fNow)/5.0f,0.0f,1.0f); - //ctParticles = FLOAT(ctParticles) * fPowerFactor; - - for( INDEX iStar=0; iStar1) continue; - FLOAT fFade; - if(fF<(RISING_FADE_IN*fPowerFactor)) fFade=fF*(1/(RISING_FADE_IN*fPowerFactor)); - else if (fF>(1.0f-RISING_FADE_OUT)) fFade=(1-fF)*(1/RISING_FADE_OUT); - else fFade=1.0f; - - FLOAT3D vPos = vCenter+FLOAT3D( - afStarsPositions[iStar][0]*fStretchX, - afStarsPositions[iStar][1]*fStretchY, - afStarsPositions[iStar][2]*fStretchZ)*fStretchAll+vY*(fF*fStretchAll*0.5f); - vPos(1)+=sin(fF*4.0f)*0.05f*fStretchAll; - vPos(3)+=cos(fF*4.0f)*0.05f*fStretchAll; - - UBYTE ub = NormFloatToByte( fFade); - COLOR colStar = RGBToColor( ub, ub, ub>>1); - Particle_RenderSquare( vPos, fSize*fPowerFactor, 0, colStar|(UBYTE(0xFF*fPowerFactor))); - } - // all done - Particle_Flush(); -} - -#define CT_SPIRAL_PARTICLES 4 -#define CT_SPIRAL_TRAIL 10 -void Particles_Spiral( CEntity *pen, FLOAT fSize, FLOAT fHeight, - enum ParticleTexture ptTexture, INDEX ctParticles) -{ - ASSERT( ctParticles<=CT_MAX_PARTICLES_TABLE); - - FLOAT fMipFactor = Particle_GetMipFactor(); - if( fMipFactor>7.0f) return; - fMipFactor = 2.5f-fMipFactor*0.3f; - fMipFactor = Clamp( fMipFactor, 0.0f, 1.0f); - INDEX ctSpiralTrail = fMipFactor*CT_SPIRAL_TRAIL; - if( ctSpiralTrail<=0) return; - FLOAT fTrailDelta = 0.1f/fMipFactor; - - FLOAT fNow = _pTimer->GetLerpedCurrentTick(); - SetupParticleTexture( ptTexture); - const FLOATmatrix3D &m = pen->GetRotationMatrix(); - FLOAT3D vY( m(1,2), m(2,2), m(3,2)); - FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector+vY*fHeight; - - for( INDEX iStar=0; iStar>1); - Particle_RenderSquare( vPos, 0.2f, 0, colStar|0xFF); - } - } - // all done - Particle_Flush(); -} - -#define EMANATE_FADE_IN 0.2f -#define EMANATE_FADE_OUT 0.6f -#define EMANATE_TOTAL_TIME 1.0f -#define EMANATE_EXIST_TIME 0.5f -void Particles_Emanate( CEntity *pen, FLOAT fSize, FLOAT fHeight, - enum ParticleTexture ptTexture, INDEX ctParticles) -{ - ASSERT( ctParticles<=CT_MAX_PARTICLES_TABLE); - if( Particle_GetMipFactor()>7.0f) return; - - FLOAT fNow = _pTimer->GetLerpedCurrentTick(); - SetupParticleTexture( ptTexture); - const FLOATmatrix3D &m = pen->GetRotationMatrix(); - FLOAT3D vY( m(1,2), m(2,2), m(3,2)); - FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector+vY*fHeight; - - for( INDEX iStar=0; iStar1) continue; - FLOAT fFade; - if(fF(1.0f-EMANATE_FADE_OUT)) fFade=(1-fF)*(1/EMANATE_FADE_OUT); - else fFade=1.0f; - - FLOAT3D vPos = vCenter+FLOAT3D( - afStarsPositions[iStar][0], - afStarsPositions[iStar][1], - afStarsPositions[iStar][2])*fSize*(fF+0.4f); - - UBYTE ub = NormFloatToByte( fFade); - COLOR colStar = RGBToColor( ub, ub, ub>>1); - Particle_RenderSquare( vPos, 0.1f, 0, colStar|0xFF); - } - // all done - Particle_Flush(); -} - -#define WATERFALL_FOAM_FADE_IN 0.1f -#define WATERFALL_FOAM_FADE_OUT 0.4f -void Particles_WaterfallFoam(CEntity *pen, FLOAT fSizeX, FLOAT fSizeY, FLOAT fSizeZ, - FLOAT fParticleSize, FLOAT fSpeed, FLOAT fSpeedY, FLOAT fLife, INDEX ctParticles) -{ - if(fLife<=0) return; - - Particle_PrepareTexture( &_toWaterfallFoam, PBT_ADD); - Particle_SetTexturePart( 512, 512, 0, 0); - - FLOAT fNow = _pTimer->GetLerpedCurrentTick(); - const FLOATmatrix3D &m = pen->GetRotationMatrix(); - FLOAT3D vX( m(1,1), m(2,1), m(3,1)); - FLOAT3D vY( m(1,2), m(2,2), m(3,2)); - FLOAT3D vZ( m(1,3), m(2,3), m(3,3)); - FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector; - - for( INDEX iFoam=0; iFoam7.0f) return; - - FLOAT fNow = _pTimer->GetLerpedCurrentTick(); - SetupParticleTexture( ptTexture); - const FLOATmatrix3D &m = pen->GetRotationMatrix(); - FLOAT3D vX( m(1,1), m(2,1), m(3,1)); - FLOAT3D vY( m(1,2), m(2,2), m(3,2)); - FLOAT3D vZ( m(1,3), m(2,3), m(3,3)); - FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector; - - for( INDEX iStar=0; iStar1) continue; - FLOAT fFade; - if(fF(1.0f-EMANATE_FADE_OUT)) fFade=(1-fF)*(1/EMANATE_FADE_OUT); - else fFade=1.0f; - - FLOAT fX = (afStarsPositions[iStar][0]+0.5f)*fSizeX*(1+fF*fAway); - FLOAT fY = fSizeY*fF; - FLOAT fZ = (afStarsPositions[iStar][2]+0.5f)*fSizeZ*(1+fF*fAway); - FLOAT3D vPos = vCenter + vX*fX + vY*fY + vZ*fZ; - - UBYTE ub = NormFloatToByte( fFade); - COLOR colStar = RGBToColor( ub, ub, ub); - Particle_RenderSquare( vPos, fParticleSize, 0, colStar|0xFF); - } - // all done - Particle_Flush(); -} - -#define CT_FOUNTAIN_TRAIL 3 -#define FOUNTAIN_FADE_IN 0.6f -#define FOUNTAIN_FADE_OUT 0.4f -#define FOUNTAIN_TOTAL_TIME 0.6f -void Particles_Fountain( CEntity *pen, FLOAT fSize, FLOAT fHeight, - enum ParticleTexture ptTexture, INDEX ctParticles) -{ - ASSERT( ctParticles<=CT_MAX_PARTICLES_TABLE); - FLOAT fNow = _pTimer->GetLerpedCurrentTick(); - - SetupParticleTexture( ptTexture); - CTextureData *pTD = (CTextureData *) _toWaterfallGradient.GetData(); - const FLOATmatrix3D &m = pen->GetRotationMatrix(); - FLOAT3D vX( m(1,1), m(2,1), m(3,1)); - FLOAT3D vY( m(1,2), m(2,2), m(3,2)); - FLOAT3D vZ( m(1,3), m(2,3), m(3,3)); - FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector+vY*fHeight; - - for( INDEX iStar=0; iStar(1.0f-FOUNTAIN_FADE_OUT)) fFade=(1-fT)*(1/FOUNTAIN_FADE_OUT); - else fFade=1.0f; - fFade *= (CT_FOUNTAIN_TRAIL-iTrail)*(1.0f/CT_FOUNTAIN_TRAIL); - - FLOAT3D vPos = vCenter + - vX*(afStarsPositions[iStar][0]*fT*fSize) + - vY*(fT*fT*-5.0f+(afStarsPositions[iStar][1]*2+4.0f)*1.2f*fT) + - vZ*(afStarsPositions[iStar][2]*fT*fSize); - - COLOR colStar = pTD->GetTexel( FloatToInt(fFade*2048), 0); - ULONG ulA = FloatToInt( ((colStar&CT_AMASK)>>CT_ASHIFT) * fFade); - colStar = (colStar&~CT_AMASK) | (ulA<en_ulID)%CT_MAX_PARTICLES_TABLE; - Particle_SetTexturePart( 512, 512, iRnd1%3, 0); - - FLOAT fT = _pTimer->GetLerpedCurrentTick()-tmStarted; - FLOAT fBoxSize = boxOwner.Size().Length(); - for(INDEX iSmoke=0; iSmoke<2+fDamage*2; iSmoke++) - { - INDEX iRnd2 = INDEX(tmStarted*12345.0f+iSmoke+fDamage*10.0f)%(CT_MAX_PARTICLES_TABLE/2); - FLOAT fLifeTime = 2.0f+(afStarsPositions[iRnd2][0]+0.5f)*2.0f; - FLOAT fRatio = CalculateRatio(fT, 0, fLifeTime, 0.4f, 0.6f); - - FLOAT fRndAppearX = afStarsPositions[iRnd2][0]*fBoxSize*0.125f; - FLOAT fRndAppearZ = afStarsPositions[iRnd2][2]*fBoxSize*0.125f; - FLOAT3D vPos = pen->GetLerpedPlacement().pl_PositionVector; - vPos(1) += fRndAppearX; - vPos(3) += fRndAppearZ; - vPos(2) += ((afStarsPositions[iRnd2+4][1]+0.5f)*2.0f+1.5f)*fT+boxOwner.Size()(2)*0.0025f; - - COLOR col = C_dGRAY|UBYTE(64.0f*fRatio); - FLOAT fRotation = afStarsPositions[iRnd2+5][0]*360+fT*200.0f*afStarsPositions[iRnd2+3][0]; - FLOAT fSize = - 0.025f*fDamage+ - (afStarsPositions[iRnd2+6][2]+0.5f)*0.075 + - (0.15f+(afStarsPositions[iRnd2+2][1]+0.5f)*0.075f*fBoxSize)*fT; - Particle_RenderSquare( vPos, fSize, fRotation, col); - } - - // all done - Particle_Flush(); -} - -#define RUNNING_DUST_TRAIL_POSITIONS 3*20 -void Particles_RunningDust_Prepare(CEntity *pen) -{ - pen->GetLastPositions(RUNNING_DUST_TRAIL_POSITIONS); -} -void Particles_RunningDust(CEntity *pen) -{ - Particle_PrepareTexture( &_toBulletSmoke, PBT_BLEND); - CLastPositions *plp = pen->GetLastPositions(RUNNING_DUST_TRAIL_POSITIONS); - FLOAT3D vOldPos = plp->GetPosition(1); - for(INDEX iPos = 2; iPoslp_ctUsed; iPos++) - { - FLOAT3D vPos = plp->GetPosition(iPos); - if( (vPos-vOldPos).Length()<1.0f) continue; - FLOAT tmStarted = _pTimer->CurrentTick()-iPos*_pTimer->TickQuantum; - INDEX iRnd = INDEX(Abs(vPos(1)*1234.234f+vPos(2)*9834.123f+vPos(3)*543.532f+pen->en_ulID))%(CT_MAX_PARTICLES_TABLE/2); - if( iRnd&3) continue; - - INDEX iRndTex = iRnd*324561+pen->en_ulID; - Particle_SetTexturePart( 512, 512, iRndTex%3, 0); - - FLOAT fLifeTime = 2.8f-(afStarsPositions[iRnd][1]+0.5f)*1.0f; - - FLOAT fT = _pTimer->GetLerpedCurrentTick()-tmStarted; - FLOAT fRatio = CalculateRatio(fT, 0, fLifeTime, 0.1f, 0.25f); - - FLOAT fRndAppearX = afStarsPositions[iRnd][0]*1.0f; - FLOAT fRndSpeedY = (afStarsPositions[iRnd][1]+0.5f)*0.5f; - FLOAT fRndAppearZ = afStarsPositions[iRnd][2]*1.0f; - vPos(1) += fRndAppearX; - vPos(2) += (0.5f+fRndSpeedY)*fT; - vPos(3) += fRndAppearZ; - - FLOAT fRndBlend = 8.0f+(afStarsPositions[iRnd*2][1]+0.5f)*64.0f; - UBYTE ubRndH = UBYTE( (afStarsPositions[iRnd][0]+0.5f)*64); - UBYTE ubRndS = UBYTE( (afStarsPositions[iRnd][1]+0.5f)*32); - UBYTE ubRndV = UBYTE( 128+afStarsPositions[iRnd][0]*64.0f); - COLOR col = HSVToColor(ubRndH,ubRndS,ubRndV)|UBYTE(fRndBlend*fRatio); - //col=C_RED|CT_OPAQUE; - FLOAT fRotation = afStarsPositions[iRnd+5][0]*360+fT*50.0f*afStarsPositions[iRnd+3][0]; - FLOAT fSize = - 0.75f+(afStarsPositions[iRnd+6][2]+0.5f)*0.25 + // static size - (0.4f+(afStarsPositions[iRnd+2][1]+0.5f)*0.4f)*fT; // dinamic size - Particle_RenderSquare( vPos, fSize, fRotation, col); - vOldPos=vPos; - } - // all done - Particle_Flush(); -} - -void Particles_MetalParts( CEntity *pen, FLOAT tmStarted, FLOATaabbox3D boxOwner, FLOAT fDamage) -{ - Particle_PrepareTexture( &_toMetalSprayTexture, PBT_BLEND); - FLOAT fT = _pTimer->GetLerpedCurrentTick()-tmStarted; - FLOAT fGA = 30.0f; - - FLOAT fBoxSize = boxOwner.Size().Length(); - for(INDEX iPart=0; iPart<6+fDamage*3.0f; iPart++) - { - INDEX iRnd = INDEX(tmStarted*12345.0f+iPart)%CT_MAX_PARTICLES_TABLE; - FLOAT fLifeTime = 2.0f+(afStarsPositions[iRnd][0]+0.5f)*2.0f; - FLOAT fRatio = CalculateRatio(fT, 0, fLifeTime, 0.1f, 0.1f); - Particle_SetTexturePart( 256, 256, ((int(tmStarted*100.0f))%8+iPart)%8, 0); - - FLOAT3D vPos = pen->GetLerpedPlacement().pl_PositionVector; - vPos(1) += afStarsPositions[iRnd][0]*fT*15; - vPos(2) += afStarsPositions[iRnd][1]*fT*15-fGA/2.0f*fT*fT+boxOwner.Size()(2)*0.25f; - vPos(3) += afStarsPositions[iRnd][2]*fT*15; - - UBYTE ubRndH = UBYTE( 180+afStarsPositions[ int(iPart+tmStarted*10)%CT_MAX_PARTICLES_TABLE][0]*16); - UBYTE ubRndS = UBYTE( 12+(afStarsPositions[ int(iPart+tmStarted*10)%CT_MAX_PARTICLES_TABLE][1])*8); - UBYTE ubRndV = UBYTE( 192+(afStarsPositions[ int(iPart+tmStarted*10)%CT_MAX_PARTICLES_TABLE][2])*64); - //ubRndS = 0; - ubRndV = 255; - COLOR col = HSVToColor(ubRndH, ubRndS, ubRndV)|UBYTE(255.0f*fRatio); - FLOAT fRotation = fT*400.0f*afStarsPositions[iRnd][0]; - FLOAT fSize = fBoxSize*0.005f+0.125f+afStarsPositions[iRnd][1]*0.025f; - Particle_RenderSquare( vPos, fSize, fRotation, col); - } - - // all done - Particle_Flush(); -} - -#define ELECTRICITY_SPARKS_FADE_OUT_TIME 0.4f -#define ELECTRICITY_SPARKS_TOTAL_TIME 1.0f -void Particles_ElectricitySparks( CEntity *pen, FLOAT fTimeAppear, FLOAT fSize, FLOAT fHeight, INDEX ctParticles) -{ - ASSERT( ctParticles<=CT_MAX_PARTICLES_TABLE/2); - FLOAT fT = _pTimer->GetLerpedCurrentTick()-fTimeAppear; - - Particle_PrepareTexture( &_toElectricitySparks, PBT_BLEND); - Particle_SetTexturePart( 512, 1024, 0, 0); - - const FLOATmatrix3D &m = pen->GetRotationMatrix(); - FLOAT3D vX( m(1,1), m(2,1), m(3,1)); - FLOAT3D vY( m(1,2), m(2,2), m(3,2)); - FLOAT3D vZ( m(1,3), m(2,3), m(3,3)); - FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector+vY*fHeight; - - for( INDEX iSpark=0; iSparkELECTRICITY_SPARKS_TOTAL_TIME) - { - fFade=0; - } - else if(fT>ELECTRICITY_SPARKS_FADE_OUT_TIME) - { - fFade=-1.0f/(ELECTRICITY_SPARKS_TOTAL_TIME-ELECTRICITY_SPARKS_FADE_OUT_TIME)*(fT-ELECTRICITY_SPARKS_TOTAL_TIME); - } - else - { - fFade=1.0f; - } - - FLOAT fTold = fT-0.05f; - -#define SPARK_CURVE( time) \ - vCenter + \ - vX*(afStarsPositions[iSpark][0]*time*fSize*3) + \ - vY*(afStarsPositions[iSpark][1]*10.0f*time-(15.0f+afStarsPositions[iSpark*2][1]*15.0f)*time*time) + \ - vZ*(afStarsPositions[iSpark][2]*time*fSize*3); - - FLOAT3D vPosOld = SPARK_CURVE( fTold); - FLOAT3D vPosNew = SPARK_CURVE( fT); - - UBYTE ubR = 224+(afStarsPositions[iSpark][2]+0.5f)*32; - UBYTE ubG = 224+(afStarsPositions[iSpark][2]+0.5f)*32; - UBYTE ubB = 160; - UBYTE ubA = FloatToInt( 255 * fFade); - COLOR colStar = RGBToColor( ubR, ubG, ubB) | ubA; - Particle_RenderLine( vPosOld, vPosNew, 0.075f, colStar); - } - // all done - Particle_Flush(); -} - -void Particles_LavaErupting(CEntity *pen, FLOAT fStretchAll, FLOAT fSize, - FLOAT fStretchX, FLOAT fStretchY, FLOAT fStretchZ, - FLOAT fActivateTime) -{ - FLOAT fT = _pTimer->GetLerpedCurrentTick()-fActivateTime; - if( fT>10.0f) return; - - Particle_PrepareTexture( &_toLavaEruptingTexture, PBT_ADD); - INDEX iTexture = ((ULONG)fActivateTime)%3; - Particle_SetTexturePart( 512, 512, iTexture, 0); - FLOAT fGA = ((CMovableEntity *)pen)->en_fGravityA; - - INDEX iRnd1 = ((ULONG)fActivateTime)%CT_MAX_PARTICLES_TABLE; - INDEX iRnd2 = (~(ULONG)fActivateTime)%CT_MAX_PARTICLES_TABLE; - - FLOAT fRndAppearX = afStarsPositions[iRnd2][0]*fStretchAll; - FLOAT fRndAppearZ = afStarsPositions[iRnd2][1]*fStretchAll; - FLOAT fRndRotation = afStarsPositions[iRnd2][2]; - - FLOAT3D vPos = pen->GetLerpedPlacement().pl_PositionVector; - vPos(1) += fRndAppearX+afStarsPositions[iRnd1][0]*fT*fStretchX*10; - vPos(2) += (fStretchY+(fStretchY*0.25f*afStarsPositions[iRnd1][1]))*fT-fGA/2.0f*fT*fT; - vPos(3) += fRndAppearZ+afStarsPositions[iRnd1][2]*fT*fStretchZ*10; - - Particle_RenderSquare( vPos, fSize+afStarsPositions[iRnd2][2]*fSize*0.5f, fRndRotation*300*fT, C_WHITE|CT_OPAQUE); - - // all done - Particle_Flush(); -} - -#define CT_ATOMIC_TRAIL 32 -void Particles_Atomic( CEntity *pen, FLOAT fSize, FLOAT fHeight, - enum ParticleTexture ptTexture, INDEX ctEllipses) -{ - ASSERT( ctEllipses<=CT_MAX_PARTICLES_TABLE); - FLOAT fMipFactor = Particle_GetMipFactor(); - if( fMipFactor>7.0f) return; - fMipFactor = 2.5f-fMipFactor*0.3f; - fMipFactor = Clamp(fMipFactor, 0.0f ,1.0f); - INDEX ctAtomicTrail = fMipFactor*CT_ATOMIC_TRAIL; - if( ctAtomicTrail<=0) return; - FLOAT fTrailDelta = 0.075f/fMipFactor; - - FLOAT fNow = _pTimer->GetLerpedCurrentTick(); - SetupParticleTexture( ptTexture); - const FLOATmatrix3D &m = pen->GetRotationMatrix(); - FLOAT3D vX( m(1,1), m(2,1), m(3,1)); - FLOAT3D vY( m(1,2), m(2,2), m(3,2)); - FLOAT3D vZ( m(1,3), m(2,3), m(3,3)); - FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector+vY*fHeight; - - for( INDEX iEllipse=0; iEllipse>3, ub>>3, ub>>2); - Particle_RenderSquare( vPos, 0.2f, 0, colStar|0xFF); - } - } - // all done - Particle_Flush(); -} - -#define CT_LIGHTNINGS 8 -void Particles_Ghostbuster(const FLOAT3D &vSrc, const FLOAT3D &vDst, INDEX ctRays, FLOAT fSize, FLOAT fPower, - FLOAT fKneeDivider/*=33.3333333f*/) -{ - Particle_PrepareTexture(&_toGhostbusterBeam, PBT_ADD); - Particle_SetTexturePart( 512, 512, 0, 0); - // get direction vector - FLOAT3D vZ = vDst-vSrc; - FLOAT fLen = vZ.Length(); - vZ.Normalize(); - - // get two normal vectors - FLOAT3D vX; - if (Abs(vZ(2))>0.5) { - vX = FLOAT3D(1.0f, 0.0f, 0.0f)*vZ; - } else { - vX = FLOAT3D(0.0f, 1.0f, 0.0f)*vZ; - } - FLOAT3D vY = vZ*vX; - const FLOAT fStep = fLen/fKneeDivider; - - for(INDEX iRay = 0; iRayGetLerpedCurrentTick()/1.5f; - FLOAT fDT = fT-INDEX(fT); - FLOAT fFade = 1-fDT*4.0f; - - if( fFade>1 || fFade<=0) continue; - UBYTE ubFade = NormFloatToByte(fFade*fPower); - COLOR colFade = RGBToColor( ubFade, ubFade, ubFade); - for(FLOAT fPos=fStep; fPosGetLerpedPlacement().pl_PositionVector; - - vPos(1) -= fGridSize*ctGrids/2; - vPos(3) -= fGridSize*ctGrids/2; - - SnapFloat( vPos(1), fGridSize); - SnapFloat( vPos(2), fGridSize); - SnapFloat( vPos(3), fGridSize); - FLOAT fNow = _pTimer->GetLerpedCurrentTick(); - - Particle_PrepareTexture(&_toRaindrop, PBT_BLEND); - Particle_SetTexturePart( 512, 4096, 0, 0); - - FLOAT fMinX = boxRainMap.Min()(1); - FLOAT fMinY = boxRainMap.Min()(2); - FLOAT fMinZ = boxRainMap.Min()(3); - FLOAT fSizeX = boxRainMap.Size()(1); - FLOAT fSizeY = boxRainMap.Size()(2); - FLOAT fSizeZ = boxRainMap.Size()(3); - PIX pixRainMapW = 1; - PIX pixRainMapH = 1; - - if( ptdRainMap != NULL) - { - pixRainMapW = ptdRainMap->GetPixWidth(); - pixRainMapH = ptdRainMap->GetPixHeight(); - } - - //INDEX ctDiscarded=0; - for( INDEX iZ=0; iZ=0 && pixX=0 && pixZGetTexel( pixX, pixZ); - FLOAT fRainMapY = fMinY+((col>>8)&0xFF)/255.0f*fSizeY; - - FLOAT fRainY = vRender(2); - // if tested raindrop is below ceiling - if( fRainY<=fRainMapY) - { - // don't render it - continue; - } else if (fRainY-fSizeGetLerpedPlacement().pl_PositionVector; - - vPos(1) -= fGridSize*ctGrids/2; - vPos(3) -= fGridSize*ctGrids/2; - - SnapFloat( vPos(1), fGridSize); - SnapFloat( vPos(2), fGridSize); - SnapFloat( vPos(3), fGridSize); - FLOAT fNow = _pTimer->GetLerpedCurrentTick(); - - Particle_PrepareTexture(&_toSnowdrop, PBT_BLEND); - Particle_SetTexturePart( 512, 512, 0, 0); - - for( INDEX iZ=0; iZ0.5) - { - vX = FLOAT3D(1.0f, 0.0f, 0.0f)*vZ; - } - else - { - vX = FLOAT3D(0.0f, 1.0f, 0.0f)*vZ; - } - // we found ortonormal vectors - FLOAT3D vY = vZ*vX; - - FLOAT fAllowRnd = 4.0f/fRandomDivider; - fRandomDivider+=1.0f; - vRenderDest = vSrc+ - vZ*fKneeLen + - vX*(fAllowRnd*afStarsPositions[iRnd][0]*fKneeLen) + - vY*(fAllowRnd*afStarsPositions[iRnd][1]*fKneeLen); - // get new rnd index - iRnd = (iRnd+1) % CT_MAX_PARTICLES_TABLE; - // see if we will spawn new branch of lightning - FLOAT fRnd = ((1-ctBranches/ctMaxBranches)*ctKnees)*afStarsPositions[iRnd][0]; - if( (fRnd < 2.0f) && (fPower>0.25f) ) - { - ctBranches++; - FLOAT3D vNewDirection = (vRenderDest-vSrc).Normalize(); - FLOAT3D vNewDst = vSrc + vNewDirection*fLen; - // recurse into new branch - RenderOneLightningBranch( vSrc, vNewDst, fPath, fTimeStart, fTimeNow, fPower/3.0f, iRnd); - } - } - - // calculate color - UBYTE ubA = UBYTE(fPower*255*fTimeKiller); - // render line - Particle_RenderLine( vSrc, vRenderDest, fPower*2, C_WHITE|ubA); - // add traveled path - fPath += (vRenderDest-vSrc).Length(); - if( fPath/LIGHTNING_SPEED > fPassedTime) - { - bRenderInProgress = FALSE; - } - vSrc = vRenderDest; - } -} - -void Particles_Lightning( FLOAT3D vSrc, FLOAT3D vDst, FLOAT fTimeStart) -{ - Particle_PrepareTexture(&_toLightning, PBT_ADDALPHA); - Particle_SetTexturePart( 512, 512, 0, 0); - - FLOAT fTimeNow = _pTimer->GetLerpedCurrentTick(); - // get rnd index - INDEX iRnd = (INDEX( fTimeStart*100))%CT_MAX_PARTICLES_TABLE; - RenderOneLightningBranch( vSrc, vDst, 0, fTimeStart, fTimeNow, 1.0f, iRnd); - - // all done - Particle_Flush(); -} - -#define CT_SANDFLOW_TRAIL 3 -#define SANDFLOW_FADE_OUT 0.25f -#define SANDFLOW_TOTAL_TIME 1.0f -void Particles_SandFlow( CEntity *pen, FLOAT fStretchAll, FLOAT fSize, FLOAT fHeight, FLOAT fStartTime, FLOAT fStopTime, - INDEX ctParticles) -{ - ASSERT( ctParticles<=CT_MAX_PARTICLES_TABLE); - FLOAT fNow = _pTimer->GetLerpedCurrentTick(); - - SetupParticleTexture( PT_SANDFLOW); - CTextureData *pTD = (CTextureData *) _toSandFlowGradient.GetData(); - const FLOATmatrix3D &m = pen->GetRotationMatrix(); - FLOAT3D vX( m(1,1), m(2,1), m(3,1)); - FLOAT3D vY( m(1,2), m(2,2), m(3,2)); - FLOAT3D vZ( m(1,3), m(2,3), m(3,3)); - FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector; - - FLOAT fPowerFactor = Clamp((fNow - fStartTime)/2.0f,0.0f,1.0f); - fPowerFactor *= Clamp(1+(fStopTime-fNow)/2.0f,0.0f,1.0f); - ctParticles = FLOAT(ctParticles) * fPowerFactor; - fHeight *= fPowerFactor; - for( INDEX iStar=0; iStarfStopTime+2.0f) ) continue; - FLOAT fFade; - if (fT>(1.0f-SANDFLOW_FADE_OUT)) fFade=(1-fT)*(1/SANDFLOW_FADE_OUT); - else fFade=1.0f; - fFade *= (CT_SANDFLOW_TRAIL-iTrail)*(1.0f/CT_SANDFLOW_TRAIL); - - FLOAT3D vPos = vCenter + - vX*(afStarsPositions[iStar][0]*fStretchAll*fPowerFactor+fHeight*fT) + - vY*(fT*fT*-5.0f+(afStarsPositions[iStar][1]*fPowerFactor*0.1)) + - vZ*(afStarsPositions[iStar][2]*fPowerFactor*fT*fStretchAll); - - COLOR colSand = pTD->GetTexel( FloatToInt(fT*2048), 0); - ULONG ulA = FloatToInt( ((colSand&CT_AMASK)>>CT_ASHIFT) * fFade); - colSand = (colSand&~CT_AMASK) | (ulA<GetLerpedCurrentTick(); - - SetupParticleTexture( PT_WATERFLOW); - CTextureData *pTD = (CTextureData *) _toWaterFlowGradient.GetData(); - const FLOATmatrix3D &m = pen->GetRotationMatrix(); - FLOAT3D vX( m(1,1), m(2,1), m(3,1)); - FLOAT3D vY( m(1,2), m(2,2), m(3,2)); - FLOAT3D vZ( m(1,3), m(2,3), m(3,3)); - FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector; - - FLOAT fPowerFactor = Clamp((fNow - fStartTime)/2.0f,0.0f,1.0f); - fPowerFactor *= Clamp(1+(fStopTime-fNow)/2.0f,0.0f,1.0f); - ctParticles = FLOAT(ctParticles) * fPowerFactor; - fHeight *= fPowerFactor; - for( INDEX iStar=0; iStarfStopTime+2.0f) ) continue; - FLOAT fFade; - if (fT>(1.0f-WATER_FLOW_FADE_OUT)) fFade=(1-fT)*(1/WATER_FLOW_FADE_OUT); - else fFade=1.0f; - fFade *= (CT_WATER_FLOW_TRAIL-iTrail)*(1.0f/CT_WATER_FLOW_TRAIL); - - FLOAT3D vPos = vCenter + - vX*(afStarsPositions[iStar][0]*fStretchAll*fPowerFactor+fHeight*fT) + - vY*(fT*fT*-5.0f+(afStarsPositions[iStar][1]*fPowerFactor*0.1)) + - vZ*(afStarsPositions[iStar][2]*fPowerFactor*fT*fStretchAll); - - COLOR colWater = pTD->GetTexel( FloatToInt(fT*2048), 0); - ULONG ulA = FloatToInt( ((colWater&CT_AMASK)>>CT_ASHIFT) * fFade); - colWater = (colWater&~CT_AMASK) | (ulA<GetLerpedCurrentTick(); - - SetupParticleTexture( PT_LAVAFLOW); - CTextureData *pTD = (CTextureData *) _toLavaFlowGradient.GetData(); - const FLOATmatrix3D &m = pen->GetRotationMatrix(); - FLOAT3D vX( m(1,1), m(2,1), m(3,1)); - FLOAT3D vY( m(1,2), m(2,2), m(3,2)); - FLOAT3D vZ( m(1,3), m(2,3), m(3,3)); - FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector; - - FLOAT fPowerFactor = Clamp((fNow - fStartTime)/2.0f,0.0f,1.0f); - fPowerFactor *= Clamp(1+(fStopTime-fNow)/2.0f,0.0f,1.0f); - ctParticles = FLOAT(ctParticles) * fPowerFactor; - fHeight *= fPowerFactor; - for( INDEX iStar=0; iStarfStopTime+2.0f) ) continue; - FLOAT fFade; - if (fT>(1.0f-LAVA_FLOW_FADE_OUT)) fFade=(1-fT)*(1/LAVA_FLOW_FADE_OUT); - else fFade=1.0f; - fFade *= (CT_LAVA_FLOW_TRAIL-iTrail)*(1.0f/CT_LAVA_FLOW_TRAIL); - - FLOAT3D vPos = vCenter + - vX*(afStarsPositions[iStar][0]*fStretchAll*fPowerFactor+fHeight*fT) + - vY*(fT*fT*-4.0f+(afStarsPositions[iStar][1]*fPowerFactor*0.1)) + - vZ*(afStarsPositions[iStar][2]*fPowerFactor*fT*fStretchAll); - - COLOR colLava = pTD->GetTexel( FloatToInt(fT*2048), 0); - ULONG ulA = FloatToInt( ((colLava&CT_AMASK)>>CT_ASHIFT) * fFade); - colLava = (colLava&~CT_AMASK) | (ulA<GetLerpedPlacement().pl_PositionVector; - FLOAT fFadeStart = BULLET_SPRAY_FADEOUT_START; - FLOAT fLifeTotal = BULLET_SPRAY_TOTAL_TIME; - FLOAT fFadeLen = fLifeTotal-fFadeStart; - COLOR colStones = C_WHITE; - - FLOAT fMipFactor = Particle_GetMipFactor(); - FLOAT fDisappear = 1.0f; - if( fMipFactor>8.0f) return; - if( fMipFactor>6.0f) - { - fDisappear = 1.0f-(fMipFactor-6.0f)/2.0f; - } - - FLOAT fNow = _pTimer->GetLerpedCurrentTick(); - FLOAT fT=(fNow-tmSpawn); - if( fT>fLifeTotal) return; - INDEX iRnd = INDEX( (tmSpawn*1000.0f)+pen->en_ulID) &63; - FLOAT fSizeStart; - FLOAT fSpeedStart; - FLOAT fConeMultiplier = 1.0f; - COLOR colSmoke; - - switch( eptType) - { - case EPT_BULLET_WATER: - { - Particle_PrepareTexture(&_toBulletWater, PBT_BLEND); - fSizeStart = 0.08f; - fSpeedStart = 1.75f; - fConeMultiplier = 0.125f; - - //FLOAT fFadeStart = BULLET_SPRAY_WATER_FADEOUT_START; - //FLOAT fLifeTotal = BULLET_SPRAY_WATER_TOTAL_TIME; - //FLOAT fFadeLen = fLifeTotal-fFadeStart; - - break; - } - case EPT_BULLET_SAND: - { - colSmoke = 0xFFE8C000; - Particle_PrepareTexture(&_toBulletSand, PBT_BLEND); - fSizeStart = 0.15f; - fSpeedStart = 0.75f; - break; - } - case EPT_BULLET_RED_SAND: - { - colSmoke = 0xA0402000; - colStones = 0x80503000; - Particle_PrepareTexture(&_toBulletSand, PBT_BLEND); - fSizeStart = 0.15f; - fSpeedStart = 0.75f; - break; - } - default: - { - colSmoke = C_WHITE; - Particle_PrepareTexture(&_toBulletStone, PBT_BLEND); - fSizeStart = 0.05f; - fSpeedStart = 1.5f; - } - } - - FLOAT fGA = 10.0f; - - // render particles - for( INDEX iSpray=0; iSpray<12*fDisappear; iSpray++) - { - Particle_SetTexturePart( 512, 512, iSpray&3, 0); - - FLOAT3D vRandomAngle = FLOAT3D( - afStarsPositions[ iSpray+iRnd][0]*3.0f* fConeMultiplier, - (afStarsPositions[ iSpray+iRnd][1]+1.0f)*3.0f, - afStarsPositions[ iSpray+iRnd][2]*3.0f* fConeMultiplier); - FLOAT fSpeedRnd = fSpeedStart+afStarsPositions[ iSpray+iRnd*2][2]; - FLOAT3D vPos = vEntity + (vDirection+vRandomAngle)*(fT*fSpeedRnd)+vGDir*(fT*fT*fGA); - - if( (eptType == EPT_BULLET_WATER) && (vPos(2) < vEntity(2)) ) - { - continue; - } - - FLOAT fSize = fSizeStart + afStarsPositions[ iSpray*2+iRnd*3][0]/20.0f; - FLOAT fRotation = fT*500.0f; - FLOAT fColorFactor = 1.0f; - if( fT>=fFadeStart) - { - fColorFactor = 1-fFadeLen*(fT-fFadeStart); - } - UBYTE ubColor = UBYTE(CT_OPAQUE*fColorFactor); - COLOR col = colStones|ubColor; - Particle_RenderSquare( vPos, fSize, fRotation, col); - } - Particle_Flush(); - - //--------------------------------------- - if( (fT=BULLET_SPARK_FADEOUT_START) - { - fColorFactor = 1-BULLET_SPARK_FADEOUT_LEN*(fT-BULLET_SPARK_FADEOUT_START); - } - UBYTE ubColor = UBYTE(CT_OPAQUE*fColorFactor); - COLOR col = RGBToColor(ubColor,ubColor,ubColor)|CT_OPAQUE; - Particle_RenderLine( vPos0, vPos1, 0.05f, col); - } - Particle_Flush(); - } - - //--------------------------------------- - if( (fT0.5) { - // use cross product of +x axis and plane normal as +s axis - vX = FLOAT3D(1.0f, 0.0f, 0.0f)*vY; - // if the plane is mostly vertical - } else { - // use cross product of +y axis and plane normal as +s axis - vX = FLOAT3D(0.0f, 1.0f, 0.0f)*vY; - } - // make +s axis normalized - vX.Normalize(); - - // use cross product of plane normal and +s axis as +t axis - vZ = vX*vY; - vZ.Normalize(); -} - -void Particles_EmptyShells( CEntity *pen, ShellLaunchData *asldData) -{ - FLOAT tmNow = _pTimer->GetLerpedCurrentTick(); - FLOAT fGA = ((CMovableEntity *)pen)->en_fGravityA; - FLOAT3D vGDir = ((CMovableEntity *)pen)->en_vGravityDir; - INDEX iRow, iColumn; - - for( INDEX iShell=0; iShell (tmLaunch+fLife) ) continue; - FLOAT fTRatio = fT/fLife; - INDEX iFrame = INDEX( fTRatio*16*8)%16; - iRow = iFrame/4; - iColumn = iFrame%4; - Particle_SetTexturePart( 256, 256, iColumn, iRow); - FLOAT3D vPos = (sld.sld_vPos)+(sld.sld_vSpeed*fT)+(vGDir*(fT*fT*fGA/2.0f)); - Particle_RenderSquare( vPos, 0.05f, 0, C_WHITE|CT_OPAQUE); - break; - } - case ESL_SHOTGUN: - { - FLOAT fLife = 1.5f; - if( tmNow > (tmLaunch+fLife) ) continue; - FLOAT fTRatio = fT/fLife; - INDEX iFrame = INDEX( fTRatio*16*8)%16; - iRow = 4+iFrame/4; - iColumn = iFrame%4; - Particle_SetTexturePart( 256, 256, iColumn, iRow); - FLOAT3D vPos = (sld.sld_vPos)+(sld.sld_vSpeed*fT)+(vGDir*(fT*fT*fGA/2.0f)); - Particle_RenderSquare( vPos, 0.05f, 0, C_WHITE|CT_OPAQUE); - break; - } - case ESL_BUBBLE: - { - INDEX iRnd = (INDEX(tmLaunch*1234))%CT_MAX_PARTICLES_TABLE; - FLOAT fLife = 4.0f; - if( tmNow > (tmLaunch+fLife) ) continue; - Particle_SetTexturePart( 512, 512, 2, 0); - - FLOAT3D vX, vZ; - MakeBaseFromVector( sld.sld_vUp, vX, vZ); - - FLOAT fZF = sin( afStarsPositions[iRnd+2][0]*PI); - FLOAT fXF = cos( afStarsPositions[iRnd+2][0]*PI); - - FLOAT fAmpl = ClampUp( fT+afStarsPositions[iRnd+1][1]+0.5f, 2.0f)/64; - FLOAT fFormulae = fAmpl * sin(afStarsPositions[iRnd][1]+fT*afStarsPositions[iRnd][2]*2); - - FLOAT fColorFactor = 1.0f; - if( fT>fLife/2) - { - fColorFactor = -fT+fLife; - } - UBYTE ubAlpha = UBYTE(CT_OPAQUE*fColorFactor); - ubAlpha = CT_OPAQUE; - FLOAT3D vSpeedPower = sld.sld_vSpeed/(1.0f+fT*fT); - - FLOAT3D vPos = sld.sld_vPos + - vX*fFormulae*fXF+ - vZ*fFormulae*fZF+ - sld.sld_vUp*fT/4.0f*(0.8f+afStarsPositions[iRnd][1]/8.0f)+ - vSpeedPower*fT; - FLOAT fSize = 0.02f + afStarsPositions[iRnd+3][1]*0.01f; - Particle_RenderSquare( vPos, fSize, 0, C_WHITE|ubAlpha); - break; - } - case ESL_SHOTGUN_SMOKE: - { - FLOAT fLife = 1.0f; - if( fT0.0f) - { - // render smoke - INDEX iRnd = (INDEX(tmLaunch*1234))%CT_MAX_PARTICLES_TABLE; - //FLOAT fTRatio = fT/fLife; - INDEX iColumn = 4+INDEX( iShell)%4; - Particle_SetTexturePart( 256, 256, iColumn, 2); - - FLOAT3D vPos = sld.sld_vPos + sld.sld_vUp*(afStarsPositions[iRnd][0]/2.0f+0.5f)*fT + sld.sld_vSpeed*fT/(1+fT*fT); - FLOAT fColorFactor = (fLife-fT)/fLife/(afStarsPositions[iRnd+1][0]*2+4.0f); - FLOAT fRotation = afStarsPositions[iShell][1]*200*fT; - FLOAT fSize = (0.0125f+fT/(5.0f+afStarsPositions[iRnd+1][0]*2.0f))*sld.sld_fSize; - UBYTE ubAlpha = UBYTE(CT_OPAQUE*ClampUp(fColorFactor*sld.sld_fSize, 1.0f)); - COLOR colSmoke = C_WHITE; - Particle_RenderSquare( vPos, fSize, fRotation, colSmoke|ubAlpha); - } - break; - } - case ESL_COLT_SMOKE: - { - FLOAT fLife = 1.0f; - if( fT0.0f) - { - CPlayer &plr = (CPlayer&)*pen; - CPlacement3D plPipe; - plr.GetLerpedWeaponPosition(sld.sld_vPos, plPipe); - FLOATmatrix3D m; - MakeRotationMatrixFast(m, plPipe.pl_OrientationAngle); - FLOAT3D vUp( m(1,2), m(2,2), m(3,2)); - - INDEX iRnd = (INDEX(tmLaunch*1234))%CT_MAX_PARTICLES_TABLE; - //FLOAT fTRatio = fT/fLife; - INDEX iColumn = 4+INDEX( iShell)%4; - Particle_SetTexturePart( 256, 256, iColumn, 2); - - FLOAT3D vPos = plPipe.pl_PositionVector+vUp*(afStarsPositions[iRnd][0]/4.0f+0.3f)*fT; - FLOAT fColorFactor = (fLife-fT)/fLife/(afStarsPositions[iRnd+1][0]*2+4.0f); - FLOAT fRotation = afStarsPositions[iShell][1]*500*fT; - FLOAT fSize = 0.0025f+fT/(10.0f+(afStarsPositions[iRnd+1][0]+0.5f)*10.0f); - UBYTE ubAlpha = UBYTE(CT_OPAQUE*fColorFactor); - COLOR colSmoke = C_WHITE; - Particle_RenderSquare( vPos, fSize, fRotation, colSmoke|ubAlpha); - } - break; - } - } - } - Particle_Flush(); -} - -#define FADE_IN_LENGHT 1.0f -#define FADE_OUT_LENGHT 1.5f -#define FADE_IN_START 0.0f -#define SPIRIT_SPIRAL_START 1.0f -#define FADE_OUT_START 1.75f - -#define FADE_IN_END (FADE_IN_START+FADE_IN_LENGHT) -#define FADE_OUT_END (FADE_OUT_START+FADE_OUT_LENGHT) - -void Particles_Death(CEntity *pen, TIME tmStart) -{ - FLOAT fMipFactor = Particle_GetMipFactor(); - BOOL bVisible = pen->en_pmoModelObject->IsModelVisible( fMipFactor); - if( !bVisible) return; - - FLOAT fTime = _pTimer->GetLerpedCurrentTick()-tmStart; - // don't render particles before fade in and after fadeout - if( (fTimeFADE_OUT_END)) { - return; - } - FLOAT fPowerTime = pow(fTime-SPIRIT_SPIRAL_START, 2.5f); - - // fill array with absolute vertices of entity's model and its attached models - pen->GetModelVerticesAbsolute(avVertices, 0.05f, fMipFactor); - - // get entity position and orientation - const FLOATmatrix3D &m = pen->GetRotationMatrix(); - FLOAT3D vX( m(1,1), m(2,1), m(3,1)); - FLOAT3D vY( m(1,2), m(2,2), m(3,2)); - FLOAT3D vZ( m(1,3), m(2,3), m(3,3)); - FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector; - - SetupParticleTexture( PT_STAR07); - - // calculate color factor (for fade in/out) - FLOAT fColorFactor = 1.0f; - if( (fTime>=FADE_IN_START) && (fTime<=FADE_IN_END)) - { - fColorFactor = 1/FADE_IN_LENGHT*(fTime-FADE_IN_START); - } - else if( (fTime>=FADE_OUT_START) && (fTime<=FADE_OUT_END)) - { - fColorFactor = -1/FADE_OUT_LENGHT*(fTime-FADE_OUT_END); - } - - UBYTE ubColor = UBYTE(CT_OPAQUE*fColorFactor); - COLOR col = RGBToColor(ubColor,ubColor,ubColor)|CT_OPAQUE; - - INDEX ctVtx = avVertices.Count(); - FLOAT fSpeedFactor = 1.0f/ctVtx; - - // get corp size - FLOATaabbox3D box; - pen->en_pmoModelObject->GetCurrentFrameBBox(box); - FLOAT fHeightStretch = box.Size()(2); - - FLOAT fStep = ClampDn( fMipFactor, 1.0f); - for( FLOAT fVtx=0.0f; fVtxen_pmoModelObject->IsModelVisible( fMipFactor); - if( !bVisible) return; - - FLOAT fTime = _pTimer->GetLerpedCurrentTick()-tmStart; - // don't render particles before fade in and after fadeout - if( (fTimeAPPEAR_OUT_END)) { - return; - } - //FLOAT fPowerTime = pow(fTime-SPIRIT_SPIRAL_START, 2.5f); - - // fill array with absolute vertices of entity's model and its attached models - pen->GetModelVerticesAbsolute(avVertices, 0.05f, fMipFactor); - - // get entity position and orientation - const FLOATmatrix3D &m = pen->GetRotationMatrix(); - FLOAT3D vX( m(1,1), m(2,1), m(3,1)); - FLOAT3D vY( m(1,2), m(2,2), m(3,2)); - FLOAT3D vZ( m(1,3), m(2,3), m(3,3)); - //FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector; - - SetupParticleTexture( PT_STAR07); - - // calculate color factor (for fade in/out) - FLOAT fColorFactor = 1.0f; - if( (fTime>=APPEAR_IN_START) && (fTime<=APPEAR_IN_END)) - { - fColorFactor = 1/APPEAR_IN_LENGHT*(fTime-APPEAR_IN_START); - } - else if( (fTime>=APPEAR_OUT_START) && (fTime<=APPEAR_OUT_END)) - { - fColorFactor = -1/APPEAR_OUT_LENGHT*(fTime-APPEAR_OUT_END); - } - - UBYTE ubColor = UBYTE(CT_OPAQUE*fColorFactor); - COLOR col = RGBToColor(ubColor,ubColor,ubColor)|CT_OPAQUE; - - INDEX ctVtx = avVertices.Count(); - //FLOAT fSpeedFactor = 1.0f/ctVtx; - - // get corp size - FLOATaabbox3D box; - pen->en_pmoModelObject->GetCurrentFrameBBox(box); - //FLOAT fHeightStretch = box.Size()(2); - - FLOAT fStep = ClampDn( fMipFactor, 1.0f); - for( FLOAT fVtx=0.0f; fVtxGetLerpedPlacement().pl_PositionVector; - FLOAT fBoxSize = boxOwner.Size().Length()*0.1f; - FLOAT fEnemySizeModifier = (fBoxSize-0.2)/1.0f+1.0f; - FLOAT fRotation = 0.0f; - - // readout blood type - const INDEX iBloodType = GetSP()->sp_iBlood; - - // determine time difference - FLOAT fNow = _pTimer->GetLerpedCurrentTick(); - - // prepare texture - switch(sptType) { - case SPT_BLOOD: - case SPT_SLIME: - { - if( iBloodType<1) return; - if( iBloodType==3) Particle_PrepareTexture( &_toFlowerSprayTexture, PBT_BLEND); - else Particle_PrepareTexture( &_toBloodSprayTexture, PBT_BLEND); - break; - } - case SPT_BONES: - { - Particle_PrepareTexture( &_toBonesSprayTexture, PBT_BLEND); - break; - } - case SPT_FEATHER: - { - Particle_PrepareTexture( &_toFeatherSprayTexture, PBT_BLEND); - fDamagePower*=2.0f; - break; - } - case SPT_STONES: - { - Particle_PrepareTexture( &_toStonesSprayTexture, PBT_BLEND); - fDamagePower*=3.0f; - break; - } - case SPT_WOOD: - { - Particle_PrepareTexture( &_toWoodSprayTexture, PBT_BLEND); - fDamagePower*=5.0f; - break; - } - case SPT_SMALL_LAVA_STONES: - { - Particle_PrepareTexture( &_toLavaSprayTexture, PBT_BLEND); - fDamagePower *= 0.75f; - break; - } - case SPT_LAVA_STONES: - { - Particle_PrepareTexture( &_toLavaSprayTexture, PBT_BLEND); - fDamagePower *=3.0f; - break; - } - case SPT_BEAST_PROJECTILE_SPRAY: - { - Particle_PrepareTexture( &_toBeastProjectileSprayTexture, PBT_BLEND); - fDamagePower*=3.0f; - break; - } - case SPT_ELECTRICITY_SPARKS: - { - Particle_PrepareTexture( &_toMetalSprayTexture, PBT_BLEND); - break; - } - default: ASSERT(FALSE); - return; - } - - FLOAT fT=(fNow-tmStarted); - for( INDEX iSpray=0; iSprayBLOOD_SPRAY_FADE_OUT_START) - { - fSize=(-1/(BLOOD_SPRAY_TOTAL_TIME-BLOOD_SPRAY_FADE_OUT_START))*(fT-BLOOD_SPRAY_TOTAL_TIME); - fFade = fSize; - } - else if( fT>BLOOD_SPRAY_TOTAL_TIME) - { - fSize=0.0f; - fFade =0.0f; - } - else - { - fSize=1.0f; - fFade = fSize; - } - FLOAT fMipFactor = Particle_GetMipFactor(); - FLOAT fMipSizeAffector = Clamp( fMipFactor/4.0f, 0.05f, 1.0f); - fSize *= fMipSizeAffector*fDamagePower*fEnemySizeModifier; - - FLOAT3D vRandomAngle = FLOAT3D( - afStarsPositions[ iSpray][0]*1.75f, - (afStarsPositions[ iSpray][1]+1.0f)*1.0f, - afStarsPositions[ iSpray][2]*1.75f); - FLOAT fSpeedModifier = afStarsPositions[ iSpray+BLOOD_SPRAYS][0]*0.5f; - - FLOAT fSpeed = BLOOD_SPRAY_SPEED_MIN+(BLOOD_SPRAY_TOTAL_TIME-fT)/BLOOD_SPRAY_TOTAL_TIME; - FLOAT3D vPos = vWoundPos + (vSpilDirection+vRandomAngle)*(fT*(fSpeed+fSpeedModifier))+vGDir*(fT*fT*fGA/4.0f); - - UBYTE ubAlpha = UBYTE(CT_OPAQUE*fFade); - FLOAT fSizeModifier = afStarsPositions[ int(iSpray+tmStarted*50)%CT_MAX_PARTICLES_TABLE][1]*0.5+1.0f; - - COLOR col = C_WHITE|CT_OPAQUE; - // prepare texture - switch(sptType) { - case SPT_BLOOD: - { - UBYTE ubRndCol = UBYTE( 128+afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][0]*64); - if( iBloodType==2) col = RGBAToColor( ubRndCol, 0, 0, ubAlpha); - if( iBloodType==1) col = RGBAToColor( 0, ubRndCol, 0, ubAlpha); - break; - } - case SPT_SLIME: - { - UBYTE ubRndCol = UBYTE( 128+afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][0]*64); - if( iBloodType!=3) col = RGBAToColor(0, ubRndCol, 0, ubAlpha); - break; - } - case SPT_BONES: - { - UBYTE ubRndH = UBYTE( 8+afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][0]*16); - UBYTE ubRndS = UBYTE( 96+(afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][1]+0.5)*64); - UBYTE ubRndV = UBYTE( 64+(afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][2])*64); - col = HSVToColor(ubRndH, ubRndS, ubRndV)|ubAlpha; - fSize/=1.5f; - break; - } - case SPT_FEATHER: - { - if(iSpray>=BLOOD_SPRAYS/2) - { - UBYTE ubRndCol = UBYTE( 128+afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][0]*64); - if( iBloodType==2) col = RGBAToColor( ubRndCol, 0, 0, ubAlpha); - if( iBloodType==1) col = RGBAToColor( 0, ubRndCol, 0, ubAlpha); - } - else - { - UBYTE ubRndH = UBYTE( 32+afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][0]*16); - //UBYTE ubRndS = UBYTE( 127+(afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][1]+0.5)*128); - UBYTE ubRndV = UBYTE( 159+(afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][2])*192); - col = HSVToColor(ubRndH, 0, ubRndV)|ubAlpha; - fSize/=2.0f; - fRotation = fT*200.0f; - } - break; - } - case SPT_STONES: - { - UBYTE ubRndH = UBYTE( 24+afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][0]*16); - UBYTE ubRndS = UBYTE( 32+(afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][1]+0.5)*64); - UBYTE ubRndV = UBYTE( 196+(afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][2])*128); - col = HSVToColor(ubRndH, ubRndS, ubRndV)|ubAlpha; - fSize*=0.10f; - fRotation = fT*200.0f; - break; - } - case SPT_WOOD: - { - UBYTE ubRndH = UBYTE( 16+afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][0]*16); - UBYTE ubRndS = UBYTE( 96+(afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][1]+0.5)*32); - UBYTE ubRndV = UBYTE( 96+(afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][2])*96); - col = HSVToColor(ubRndH, ubRndS, ubRndV)|ubAlpha; - fSize*=0.15f; - fRotation = fT*300.0f; - break; - } - case SPT_LAVA_STONES: - case SPT_SMALL_LAVA_STONES: - { - col = C_WHITE|ubAlpha; - fSize/=12.0f; - fRotation = fT*200.0f; - break; - } - case SPT_BEAST_PROJECTILE_SPRAY: - { - col = C_WHITE|ubAlpha; - fSize/=12.0f; - fRotation = fT*200.0f; - break; - } - case SPT_ELECTRICITY_SPARKS: - { - UBYTE ubRndH = UBYTE( 180+afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][0]*16); - UBYTE ubRndS = UBYTE( 32+(afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][1]+0.5)*16); - UBYTE ubRndV = UBYTE( 192+(afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][2])*64); - ubRndS = 0; - ubRndV = 255; - col = HSVToColor(ubRndH, ubRndS, ubRndV)|ubAlpha; - fSize/=32.0f; - fRotation = fT*200.0f; - break; - } - } - Particle_RenderSquare( vPos, 0.25f*fSize*fSizeModifier, fRotation, col); - } - - // all done - Particle_Flush(); -} - -// spray some stones along obelisk -void Particles_DestroyingObelisk(CEntity *penSpray, FLOAT tmStarted) -{ - FLOAT fNow = _pTimer->GetLerpedCurrentTick(); - FLOAT fT=(fNow-tmStarted); - Particle_PrepareTexture( &_toStonesSprayTexture, PBT_BLEND); - - FLOAT fTotalTime = 10.0f; - FLOAT fFadeOutStart = 7.5f; - FLOAT fFadeInEnd = 1.0f; - FLOAT3D vG = FLOAT3D(0.0f,-20.0f,0.0f); - - for( INDEX iStone=0; iStone<128; iStone++) - { - INDEX idx = int(iStone+tmStarted*33)%CT_MAX_PARTICLES_TABLE; - FLOAT3D vSpeed = FLOAT3D( - afStarsPositions[ idx][0], - afStarsPositions[ idx][1], - afStarsPositions[ idx][2]); - vSpeed(2) += 0.25f; - vSpeed *= 50.0f; - - // calculate position - FLOAT3D vPos = penSpray->GetPlacement().pl_PositionVector + - vSpeed*fT + - vG*fT*fT; - vPos(2) += (afStarsPositions[ int(iStone+tmStarted*100)%CT_MAX_PARTICLES_TABLE][1]+0.5)*116.0f; - - FLOAT fFade; - // apply fade - if( fTfFadeOutStart) - { - fFade = (-1/(fTotalTime-fFadeOutStart))*(fT-fTotalTime); - } - else if( fT>fTotalTime) - { - fFade =0.0f; - } - else - { - fFade = 1.0f; - } - - UBYTE ubRndH = UBYTE( 16+afStarsPositions[ int(iStone+tmStarted*10)%CT_MAX_PARTICLES_TABLE][0]*8); - UBYTE ubRndS = UBYTE( 96+(afStarsPositions[ int(iStone+tmStarted*10)%CT_MAX_PARTICLES_TABLE][1]+0.5)*64); - UBYTE ubRndV = UBYTE( 128+(afStarsPositions[ int(iStone+tmStarted*10)%CT_MAX_PARTICLES_TABLE][2])*64); - UBYTE ubAlpha = UBYTE(CT_OPAQUE*fFade); - COLOR col = HSVToColor(ubRndH, ubRndS, ubRndV)|ubAlpha; - - FLOAT fSize=(afStarsPositions[ int(iStone+tmStarted*100)%CT_MAX_PARTICLES_TABLE][2]+1.0f)*1.5f; - FLOAT fRotation = fT*200.0f; - - Particle_SetTexturePart( 256, 256, ((int(tmStarted*100.0f))%8+iStone)%8, 0); - Particle_RenderSquare( vPos, fSize, fRotation, col); - } - // all done - Particle_Flush(); -} - -// spray some stones along pylon -void Particles_DestroyingPylon(CEntity *penSpray, FLOAT3D vDamageDir, FLOAT tmStarted) -{ - FLOAT fNow = _pTimer->GetLerpedCurrentTick(); - FLOAT fT=(fNow-tmStarted); - Particle_PrepareTexture( &_toStonesSprayTexture, PBT_BLEND); - - FLOAT fTotalTime = 10.0f; - FLOAT fFadeOutStart = 7.5f; - FLOAT fFadeInEnd = 1.0f; - FLOAT3D vG = FLOAT3D(0.0f,-20.0f,0.0f); - const FLOATmatrix3D &m = penSpray->GetRotationMatrix(); - - for( INDEX iStone=0; iStone<128; iStone++) - { - INDEX idx = int(iStone+tmStarted*33)%CT_MAX_PARTICLES_TABLE; - FLOAT3D vSpeed = vDamageDir+FLOAT3D( - afStarsPositions[ idx][0], - afStarsPositions[ idx][1], - afStarsPositions[ idx][2]); - vSpeed *= 50.0f; - - // calculate position - FLOAT3D vPos = penSpray->GetPlacement().pl_PositionVector + - vSpeed*fT*m + - vG*fT*fT; - FLOAT3D vOffset = FLOAT3D(0.0f,0.0f,0.0f); - vOffset(1) = (afStarsPositions[ int(iStone+tmStarted*100)%CT_MAX_PARTICLES_TABLE][1])*32.0f; - vOffset(2) = (afStarsPositions[ int(iStone+tmStarted*100)%CT_MAX_PARTICLES_TABLE][2]+0.5)*56.0f; - vPos += vOffset*m; - - FLOAT fFade; - // apply fade - if( fTfFadeOutStart) - { - fFade = (-1/(fTotalTime-fFadeOutStart))*(fT-fTotalTime); - } - else if( fT>fTotalTime) - { - fFade =0.0f; - } - else - { - fFade = 1.0f; - } - - UBYTE ubRndH = UBYTE( 16+afStarsPositions[ int(iStone+tmStarted*10)%CT_MAX_PARTICLES_TABLE][0]*8); - UBYTE ubRndS = UBYTE( 96+(afStarsPositions[ int(iStone+tmStarted*10)%CT_MAX_PARTICLES_TABLE][1]+0.5)*64); - UBYTE ubRndV = UBYTE( 128+(afStarsPositions[ int(iStone+tmStarted*10)%CT_MAX_PARTICLES_TABLE][2])*64); - UBYTE ubAlpha = UBYTE(CT_OPAQUE*fFade); - COLOR col = HSVToColor(ubRndH, ubRndS, ubRndV)|ubAlpha; - - FLOAT fSize=(afStarsPositions[ int(iStone+tmStarted*100)%CT_MAX_PARTICLES_TABLE][2]+1.0f)*1.5f; - FLOAT fRotation = fT*200.0f; - - Particle_SetTexturePart( 256, 256, ((int(tmStarted*100.0f))%8+iStone)%8, 0); - Particle_RenderSquare( vPos, fSize, fRotation, col); - } - // all done - Particle_Flush(); -} - -// spray some stones in the air -void Particles_HitGround(CEntity *penSpray, FLOAT tmStarted, FLOAT fSizeMultiplier) -{ - FLOAT fNow = _pTimer->GetLerpedCurrentTick(); - FLOAT fT=(fNow-tmStarted); - Particle_PrepareTexture( &_toStonesSprayTexture, PBT_BLEND); - - FLOAT fTotalTime = 10.0f; - FLOAT fFadeOutStart = 7.5f; - FLOAT fFadeInEnd = 1.0f; - FLOAT3D vG = FLOAT3D(0.0f,-30.0f,0.0f); - - for( INDEX iStone=0; iStone<64; iStone++) - { - INDEX idx = int(iStone+tmStarted*33)%CT_MAX_PARTICLES_TABLE; - FLOAT3D vSpeed = FLOAT3D( - afStarsPositions[ idx][0]*1.5f, - (afStarsPositions[ idx][1]+0.5f)*3, - afStarsPositions[ idx][2]*1.5f); - FLOAT fSpeedMultiplier = (fSizeMultiplier-1)*(0.5f-1.0f)/(0.025f-1.0f)+1.0f; - vSpeed *= 50.0f*fSpeedMultiplier; - - // calculate position - FLOAT3D vPos = penSpray->GetPlacement().pl_PositionVector + - vSpeed*fT + - vG*fT*fT; - - FLOAT fFade; - // apply fade - if( fTfFadeOutStart) - { - fFade = (-1/(fTotalTime-fFadeOutStart))*(fT-fTotalTime); - } - else if( fT>fTotalTime) - { - fFade =0.0f; - } - else - { - fFade = 1.0f; - } - - UBYTE ubRndH = UBYTE( 16+afStarsPositions[ int(iStone+tmStarted*10)%CT_MAX_PARTICLES_TABLE][0]*8); - UBYTE ubRndS = UBYTE( 96+(afStarsPositions[ int(iStone+tmStarted*10)%CT_MAX_PARTICLES_TABLE][1]+0.5)*64); - UBYTE ubRndV = UBYTE( 128+(afStarsPositions[ int(iStone+tmStarted*10)%CT_MAX_PARTICLES_TABLE][2])*64); - UBYTE ubAlpha = UBYTE(CT_OPAQUE*fFade); - COLOR col = HSVToColor(ubRndH, ubRndS, ubRndV)|ubAlpha; - - FLOAT fSize=(afStarsPositions[ int(iStone+tmStarted*100)%CT_MAX_PARTICLES_TABLE][2]+1.0f)*4.0f*fSizeMultiplier; - FLOAT fRotation = fT*200.0f; - - Particle_SetTexturePart( 256, 256, ((int(tmStarted*100.0f))%8+iStone)%8, 0); - Particle_RenderSquare( vPos, fSize, fRotation, col); - } - // all done - Particle_Flush(); -} +#include "../StdH/StdH.h" +#include "Entities/BloodSpray.h" +#include "Entities/PlayerWeapons.h" +#include "Entities/WorldSettingsController.h" +#include "Entities/BackgroundViewer.h" + +static CTextureObject _toRomboidTrail; +static CTextureObject _toBombTrail; +static CTextureObject _toFirecrackerTrail; +static CTextureObject _toSpiralTrail; +static CTextureObject _toColoredStarsTrail; +static CTextureObject _toFireball01Trail; +static CTextureObject _toGrenadeTrail; +static CTextureObject _toCannonBall; +static CTextureObject _toRocketTrail; +static CTextureObject _toVerticalGradient; +static CTextureObject _toVerticalGradientAlpha; +static CTextureObject _toBlood01Trail; +static CTextureObject _toLavaTrailGradient; +static CTextureObject _toLavaTrailSmoke; +static CTextureObject _toFlamethrowerTrail; +static CTextureObject _toBoubble01; +static CTextureObject _toBoubble02; +static CTextureObject _toBoubble03; +static CTextureObject _toStar01; +static CTextureObject _toStar02; +static CTextureObject _toStar03; +static CTextureObject _toStar04; +static CTextureObject _toStar05; +static CTextureObject _toStar06; +static CTextureObject _toStar07; +static CTextureObject _toStar08; +static CTextureObject _toBlood; +static CTextureObject _toWaterfallGradient; +static CTextureObject _toGhostbusterBeam; +static CTextureObject _toLightning; +static CTextureObject _toSand; +static CTextureObject _toSandFlowGradient; +static CTextureObject _toWater; +static CTextureObject _toWaterFlowGradient; +static CTextureObject _toLava; +static CTextureObject _toLavaFlowGradient; +static CTextureObject _toBloodSprayTexture; +static CTextureObject _toFlowerSprayTexture; +static CTextureObject _toBonesSprayTexture; +static CTextureObject _toFeatherSprayTexture; +static CTextureObject _toStonesSprayTexture; +static CTextureObject _toLavaSprayTexture; +static CTextureObject _toBeastProjectileSprayTexture; +static CTextureObject _toLavaEruptingTexture; +static CTextureObject _toWoodSprayTexture; +static CTextureObject _toLavaBombTrailSmoke; +static CTextureObject _toLavaBombTrailGradient; +static CTextureObject _toElectricitySparks; +static CTextureObject _toBeastProjectileTrailTexture; +static CTextureObject _toBeastProjectileTrailGradient; +static CTextureObject _toBeastBigProjectileTrailTexture; +static CTextureObject _toBeastBigProjectileTrailGradient; +static CTextureObject _toBeastDebrisTrailGradient; +static CTextureObject _toBeastDebrisTrailTexture; +static CTextureObject _toRaindrop; +static CTextureObject _toSnowdrop; +static CTextureObject _toBulletStone; +static CTextureObject _toBulletSand; +static CTextureObject _toBulletSpark; +static CTextureObject _toBulletSmoke; +static CTextureObject _toBulletWater; +static CTextureObject _toPlayerParticles; +static CTextureObject _toWaterfallFoam; +static CTextureObject _toMetalSprayTexture; + +// array for model vertices in absolute space +CStaticStackArray avVertices; + +#define CT_MAX_PARTICLES_TABLE 512 + +FLOAT afTimeOffsets[CT_MAX_PARTICLES_TABLE]; +FLOAT afStarsPositions[CT_MAX_PARTICLES_TABLE][3]; +UBYTE auStarsColors[CT_MAX_PARTICLES_TABLE][3]; + +void InitParticleTables(void); + +// init particle effects +void InitParticles(void) +{ + try + { + _toRomboidTrail.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\Romboid.tex")); + _toBombTrail.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\WhiteBubble.tex")); + _toFirecrackerTrail.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\FireCracker.tex")); + _toSpiralTrail.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\Smoke01.tex")); + _toColoredStarsTrail.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\Star01.tex")); + _toFireball01Trail.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\Fireball01.tex")); + _toGrenadeTrail.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\Smoke02.tex")); + _toCannonBall.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\CannonBall.tex")); + _toRocketTrail.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\Smoke06.tex")); + _toVerticalGradient.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\VerticalGradient.tex")); + _toVerticalGradientAlpha.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\VerticalGradientAlpha.tex")); + _toBlood01Trail.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\Blood02.tex")); + _toLavaTrailGradient.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\LavaTrailGradient.tex")); + _toLavaTrailSmoke.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\LavaTrailSmoke.tex")); + _toFlamethrowerTrail.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\FlameThrower01.tex")); + _toBoubble01.SetData_t(CTFILENAME("Models\\Items\\Particles\\Boubble01.tex")); + _toBoubble02.SetData_t(CTFILENAME("Models\\Items\\Particles\\Boubble02.tex")); + _toBoubble03.SetData_t(CTFILENAME("Models\\Items\\Particles\\Boubble03.tex")); + _toStar01.SetData_t(CTFILENAME("Models\\Items\\Particles\\Star01.tex")); + _toStar02.SetData_t(CTFILENAME("Models\\Items\\Particles\\Star02.tex")); + _toStar03.SetData_t(CTFILENAME("Models\\Items\\Particles\\Star03.tex")); + _toStar04.SetData_t(CTFILENAME("Models\\Items\\Particles\\Star04.tex")); + _toStar05.SetData_t(CTFILENAME("Models\\Items\\Particles\\Star05.tex")); + _toStar06.SetData_t(CTFILENAME("Models\\Items\\Particles\\Star06.tex")); + _toStar07.SetData_t(CTFILENAME("Models\\Items\\Particles\\Star07.tex")); + _toStar08.SetData_t(CTFILENAME("Models\\Items\\Particles\\Star08.tex")); + _toWaterfallGradient.SetData_t(CTFILENAME("Models\\Effects\\Heatmaps\\Waterfall08.tex")); + _toGhostbusterBeam.SetData_t(CTFILENAME("Models\\Weapons\\GhostBuster\\Projectile\\Ray.tex")); + _toLightning.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\Lightning.tex")); + _toSand.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\Sand.tex")); + _toSandFlowGradient.SetData_t(CTFILENAME("Models\\Effects\\Heatmaps\\SandFlow01.tex")); + _toWater.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\Water.tex")); + _toWaterFlowGradient.SetData_t(CTFILENAME("Models\\Effects\\Heatmaps\\WaterFlow01.tex")); + _toLava.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\Lava.tex")); + _toLavaFlowGradient.SetData_t(CTFILENAME("Models\\Effects\\Heatmaps\\LavaFlow01.tex")); + _toBloodSprayTexture.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\Blood03.tex")); + _toFlowerSprayTexture.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\Flowers.tex")); + _toBonesSprayTexture.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\BonesSpill01.tex")); + _toFeatherSprayTexture.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\FeatherSpill01.tex")); + _toStonesSprayTexture.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\StonesSpill01.tex")); + _toLavaSprayTexture.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\LavaSpill01.tex")); + _toBeastProjectileSprayTexture.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\BeastProjectileSpill.tex")); + _toLavaEruptingTexture.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\LavaErupting.tex")); + _toWoodSprayTexture.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\WoodSpill01.tex")); + _toLavaBombTrailSmoke.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\LavaBomb.tex")); + _toLavaBombTrailGradient.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\LavaBombGradient.tex")); + _toBeastDebrisTrailGradient.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\BeastDebrisTrailGradient.tex")); + _toBeastProjectileTrailTexture.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\BeastProjectileTrail.tex")); + _toBeastProjectileTrailGradient.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\BeastProjectileTrailGradient.tex")); + _toBeastBigProjectileTrailTexture.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\BeastBigProjectileTrail.tex")); + _toBeastBigProjectileTrailGradient.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\BeastBigProjectileTrailGradient.tex")); + _toBeastDebrisTrailTexture.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\BeastDebrisTrail.tex")); + _toElectricitySparks.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\ElectricitySparks.tex")); + _toRaindrop.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\Raindrop.tex")); + _toSnowdrop.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\Snowdrop.tex")); + _toBulletStone.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\BulletSpray.tex")); + _toBulletWater.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\BulletSprayWater.tex")); + _toBulletSand.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\BulletSpraySand.tex")); + _toBulletSpark.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\BulletSpark.tex")); + _toBulletSmoke.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\SmokeAnim01.tex")); + _toPlayerParticles.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\PlayerParticles.tex")); + _toWaterfallFoam.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\WaterfallFoam.tex")); + _toMetalSprayTexture.SetData_t(CTFILENAME("Textures\\Effects\\Particles\\MetalSpill.tex")); + + ((CTextureData*)_toLavaTrailGradient .GetData())->Force(TEX_STATIC); + ((CTextureData*)_toLavaBombTrailGradient .GetData())->Force(TEX_STATIC); + ((CTextureData*)_toBeastDebrisTrailGradient .GetData())->Force(TEX_STATIC); + ((CTextureData*)_toBeastProjectileTrailGradient .GetData())->Force(TEX_STATIC); + ((CTextureData*)_toBeastBigProjectileTrailGradient.GetData())->Force(TEX_STATIC); + ((CTextureData*)_toWaterfallGradient .GetData())->Force(TEX_STATIC); + ((CTextureData*)_toSandFlowGradient .GetData())->Force(TEX_STATIC); + ((CTextureData*)_toWaterFlowGradient .GetData())->Force(TEX_STATIC); + ((CTextureData*)_toLavaFlowGradient .GetData())->Force(TEX_STATIC); + } + catch(char *strError) + { + FatalError(TRANS("Unable to obtain texture: %s"), strError); + } + InitParticleTables(); +} + +// close particle effects +void CloseParticles(void) +{ + _toRomboidTrail.SetData(NULL); + _toBombTrail.SetData(NULL); + _toFirecrackerTrail.SetData(NULL); + _toSpiralTrail.SetData(NULL); + _toColoredStarsTrail.SetData(NULL); + _toFireball01Trail.SetData(NULL); + _toRocketTrail.SetData(NULL); + _toGrenadeTrail.SetData(NULL); + _toCannonBall.SetData(NULL); + _toVerticalGradient.SetData(NULL); + _toVerticalGradientAlpha.SetData(NULL); + _toBlood01Trail.SetData(NULL); + _toLavaTrailGradient.SetData(NULL); + _toWaterfallGradient.SetData(NULL); + _toGhostbusterBeam.SetData( NULL); + _toLightning.SetData( NULL); + _toLavaTrailSmoke.SetData(NULL); + _toFlamethrowerTrail.SetData(NULL); + _toBoubble01.SetData(NULL); + _toBoubble02.SetData(NULL); + _toBoubble03.SetData(NULL); + _toStar01.SetData(NULL); + _toStar02.SetData(NULL); + _toStar03.SetData(NULL); + _toStar04.SetData(NULL); + _toStar05.SetData(NULL); + _toStar06.SetData(NULL); + _toStar07.SetData(NULL); + _toStar08.SetData(NULL); + _toSand.SetData(NULL); + _toSandFlowGradient.SetData(NULL); + _toWater.SetData(NULL); + _toWaterFlowGradient.SetData(NULL); + _toLava.SetData(NULL); + _toLavaFlowGradient.SetData(NULL); + _toLavaBombTrailSmoke.SetData(NULL); + _toLavaBombTrailGradient.SetData(NULL); + _toBloodSprayTexture.SetData(NULL); + _toFlowerSprayTexture.SetData(NULL); + _toBonesSprayTexture.SetData(NULL); + _toFeatherSprayTexture.SetData(NULL); + _toStonesSprayTexture.SetData(NULL); + _toLavaSprayTexture.SetData(NULL); + _toBeastProjectileSprayTexture.SetData(NULL); + _toLavaEruptingTexture.SetData(NULL); + _toWoodSprayTexture.SetData(NULL); + _toElectricitySparks.SetData(NULL); + _toBeastDebrisTrailGradient.SetData(NULL); + _toBeastProjectileTrailTexture.SetData(NULL); + _toBeastProjectileTrailGradient.SetData(NULL); + _toBeastBigProjectileTrailTexture.SetData(NULL); + _toBeastBigProjectileTrailGradient.SetData(NULL); + _toBeastDebrisTrailTexture.SetData(NULL); + _toRaindrop.SetData(NULL); + _toSnowdrop.SetData(NULL); + _toBulletStone.SetData(NULL); + _toBulletWater.SetData(NULL); + _toBulletSand.SetData(NULL); + _toBulletSpark.SetData(NULL); + _toBulletSmoke.SetData(NULL); + _toPlayerParticles.SetData(NULL); + _toWaterfallFoam.SetData(NULL); + _toMetalSprayTexture.SetData(NULL); +} + +void Particles_ViewerLocal(CEntity *penView) +{ + ASSERT(penView!=NULL); + + // ----------- Obtain world settings controller + CWorldSettingsController *pwsc = NULL; + // obtain bcg viewer + CBackgroundViewer *penBcgViewer = (CBackgroundViewer *) penView->GetWorld()->GetBackgroundViewer(); + if( penBcgViewer != NULL) + { + // obtain world settings controller + pwsc = (CWorldSettingsController *) &*penBcgViewer->m_penWorldSettingsController; + } + + // ***** Storm appearing effects + // if world settings controller is valid + if( (pwsc != NULL) && (pwsc->m_tmStormStart != -1)) + { + FLOAT fStormFactor = pwsc->GetStormFactor(); + if( fStormFactor != 0.0f) + { + FLOATaabbox3D boxRainMap; + CTextureData *ptdRainMap; + pwsc->GetHeightMapData( ptdRainMap, boxRainMap); + Particles_Rain( penView, 1.25f, 32, fStormFactor, ptdRainMap, boxRainMap); + } + } +} + +// different particle effects +#define ROMBOID_TRAIL_POSITIONS 16 +void Particles_RomboidTrail(CEntity *pen) +{ + CLastPositions *plp = pen->GetLastPositions(ROMBOID_TRAIL_POSITIONS); + FLOAT fSeconds = _pTimer->GetLerpedCurrentTick(); + + Particle_PrepareTexture(&_toRomboidTrail, PBT_ADD); + Particle_SetTexturePart( 512, 512, 0, 0); + + for(INDEX iPos = 0; iPoslp_ctUsed; iPos++) + { + FLOAT3D vPos = plp->GetPosition(iPos); + //FLOAT fRand = rand()/FLOAT(RAND_MAX); + FLOAT fAngle = fSeconds*256+iPos*2.0f*PI/ROMBOID_TRAIL_POSITIONS; + FLOAT fSin = FLOAT(sin(fAngle)); + vPos(2) += fSin*iPos/ROMBOID_TRAIL_POSITIONS; + FLOAT fSize = (ROMBOID_TRAIL_POSITIONS-iPos)*0.5f/ROMBOID_TRAIL_POSITIONS+0.1f; + UBYTE ub = 255-iPos*255/ROMBOID_TRAIL_POSITIONS; + Particle_RenderSquare( vPos, fSize, fAngle, RGBToColor(255-ub,ub,255-ub)|ub); + } + // all done + Particle_Flush(); +} + +#define BOMB_TRAIL_POSITIONS 8 +#define BOMB_TRAIL_INTERPOSITIONS 4 +void Particles_BombTrail_Prepare(CEntity *pen) +{ + pen->GetLastPositions(BOMB_TRAIL_POSITIONS); +} +void Particles_BombTrail(CEntity *pen) +{ + CLastPositions *plp = pen->GetLastPositions(BOMB_TRAIL_POSITIONS); + + Particle_PrepareTexture(&_toBombTrail, PBT_ADD); + Particle_SetTexturePart( 512, 512, 0, 0); + + const FLOAT3D *pvPos1; + const FLOAT3D *pvPos2 = &plp->GetPosition(plp->lp_ctUsed-1); + for(INDEX iPos = plp->lp_ctUsed-1; iPos>=1; iPos--) + { + pvPos1 = pvPos2; + pvPos2 = &plp->GetPosition(iPos); + for (INDEX iInter=0; iInterGetLastPositions(FIRECRACKER_TRAIL_POSITIONS); +} +void Particles_FirecrackerTrail(CEntity *pen) +{ + CLastPositions *plp = pen->GetLastPositions(FIRECRACKER_TRAIL_POSITIONS); + Particle_PrepareTexture(&_toFirecrackerTrail, PBT_ADD); + Particle_SetTexturePart( 512, 512, 0, 0); + + if( plp->lp_ctUsed<2) return; + const FLOAT3D *pvPos1; + const FLOAT3D *pvPos2 = &plp->GetPosition(plp->lp_ctUsed-1); + INDEX iParticle = plp->lp_ctUsed*FIRECRACKER_TRAIL_INTERPOSITIONS; + for(INDEX iPos = plp->lp_ctUsed-2; iPos>=0; iPos--) + { + pvPos1 = pvPos2; + pvPos2 = &plp->GetPosition(iPos); + for (INDEX iInter=0; iInterGetLastPositions(SPIRAL_TRAIL_POSITIONS); + + FLOAT fSeconds = _pTimer->GetLerpedCurrentTick(); + Particle_PrepareTexture(&_toSpiralTrail, PBT_ADD); + Particle_SetTexturePart( 512, 512, 0, 0); + + for(INDEX iPos = 0; iPoslp_ctUsed; iPos++) + { + FLOAT3D vPos = plp->GetPosition(iPos); + FLOAT fAngle = fSeconds*32.0f+iPos*2*PI/SPIRAL_TRAIL_POSITIONS; + FLOAT fSin = FLOAT(sin(fAngle)); + FLOAT fCos = FLOAT(cos(fAngle)); + + vPos(1) += fSin*iPos*1.0f/SPIRAL_TRAIL_POSITIONS; + vPos(2) += fCos*iPos*1.0f/SPIRAL_TRAIL_POSITIONS; + + UBYTE ub = iPos*SPIRAL_TRAIL_POSITIONS; + Particle_RenderSquare( vPos, 0.2f, fAngle, RGBToColor(ub,ub,ub)|ub); + } + // all done + Particle_Flush(); +} + +static COLOR _aColors[] = { C_WHITE, C_GRAY, + C_RED, C_GREEN, C_BLUE, C_CYAN, C_MAGENTA, C_YELLOW, C_ORANGE, C_BROWN, C_PINK, + C_lRED, C_lGREEN, C_lBLUE, C_lCYAN, C_lMAGENTA, C_lYELLOW, C_lORANGE, C_lBROWN, C_lPINK +}; + +#define COLORED_STARS_TRAIL_POSITIONS 16 +void Particles_ColoredStarsTrail(CEntity *pen) +{ + CLastPositions *plp = pen->GetLastPositions(COLORED_STARS_TRAIL_POSITIONS); + FLOAT fSeconds = _pTimer->GetLerpedCurrentTick(); + + Particle_PrepareTexture(&_toColoredStarsTrail, PBT_ADD); + Particle_SetTexturePart( 512, 512, 0, 0); + + for(INDEX iPos = 0; iPoslp_ctUsed; iPos++) + { + FLOAT3D vPos1 = plp->GetPosition(iPos); + //FLOAT3D vPos2 = vPos1; + + FLOAT fAngle = fSeconds*64.0f+iPos*2*PI/COLORED_STARS_TRAIL_POSITIONS; + FLOAT fSin = FLOAT(sin(fAngle)); + //FLOAT fCos = FLOAT(cos(fAngle)); + + FLOAT fDeltaY = fSin/2.0f; + vPos1(2) += fDeltaY; + //vPos2(2) -= fDeltaY; + + FLOAT fRand = rand()/FLOAT(RAND_MAX); + INDEX iRandColor = INDEX(fRand*sizeof(_aColors)/sizeof(COLOR)); + COLOR colColor1 = _aColors[ iRandColor]; + Particle_RenderSquare( vPos1, 0.4f, fAngle, colColor1); + } + // all done + Particle_Flush(); +} + +#define WHITE_LINE_TRAIL_POSITIONS 8 +void Particles_WhiteLineTrail(CEntity *pen) +{ + CLastPositions *plp = pen->GetLastPositions(WHITE_LINE_TRAIL_POSITIONS); + FLOAT fSeconds = _pTimer->GetLerpedCurrentTick(); + + Particle_PrepareTexture(&_toSpiralTrail, PBT_ADD); + Particle_SetTexturePart( 1, 1, 256, 256); + + FLOAT3D vOldPos = plp->GetPosition(0); + for(INDEX iPos = 1; iPoslp_ctUsed; iPos++) + { + FLOAT3D vPos = plp->GetPosition(iPos); + FLOAT fAngle = fSeconds*4.0f+iPos*PI/WHITE_LINE_TRAIL_POSITIONS; + FLOAT fSin = FLOAT(sin(fAngle)); + FLOAT fCos = FLOAT(cos(fAngle)); + + vPos(1) += fSin*iPos*1.0f/WHITE_LINE_TRAIL_POSITIONS; + vPos(2) += fCos*iPos*1.0f/WHITE_LINE_TRAIL_POSITIONS; + + //UBYTE ub = 255-iPos*256/WHITE_LINE_TRAIL_POSITIONS; + FLOAT fLerpFactor = FLOAT(iPos)/WHITE_LINE_TRAIL_POSITIONS; + COLOR colColor = LerpColor( C_YELLOW, C_dRED, fLerpFactor); + Particle_RenderLine( vPos, vOldPos, 0.05f, colColor); + vOldPos =vPos; + } + // all done + Particle_Flush(); +} + + +#define FIREBALL01_TRAIL_POSITIONS 8 +#define FIREBALL01_TRAIL_INTERPOSITIONS 4 +#define FIREBALL01_TRAIL_PARTICLES (FIREBALL01_TRAIL_INTERPOSITIONS*FIREBALL01_TRAIL_POSITIONS) +void Particles_Fireball01Trail_Prepare(CEntity *pen) +{ + pen->GetLastPositions(FIREBALL01_TRAIL_POSITIONS); +} +void Particles_Fireball01Trail(CEntity *pen) +{ + CLastPositions *plp = pen->GetLastPositions(FIREBALL01_TRAIL_POSITIONS); + Particle_PrepareTexture(&_toFireball01Trail, PBT_ADD); + Particle_SetTexturePart( 512, 512, 0, 0); + + const FLOAT3D *pvPos1; + const FLOAT3D *pvPos2 = &plp->GetPosition(plp->lp_ctUsed-1); + INDEX iParticle = 0; + INDEX iParticlesLiving = plp->lp_ctUsed*FIREBALL01_TRAIL_INTERPOSITIONS; + for(INDEX iPos = plp->lp_ctUsed-2; iPos>=0; iPos--) { + pvPos1 = pvPos2; + pvPos2 = &plp->GetPosition(iPos); + COLOR colColor; + for (INDEX iInter=0; iInterGetLastPositions(GRENADE_TRAIL_POSITIONS); +} +void Particles_GrenadeTrail(CEntity *pen) +{ + CLastPositions *plp = pen->GetLastPositions(GRENADE_TRAIL_POSITIONS); + FLOAT fSeconds = _pTimer->GetLerpedCurrentTick(); + + Particle_PrepareTexture(&_toGrenadeTrail, PBT_MULTIPLY); + Particle_SetTexturePart( 512, 512, 0, 0); + + const FLOAT3D *pvPos1; + const FLOAT3D *pvPos2 = &plp->GetPosition(0); + INDEX iParticle = 0; + INDEX iParticlesLiving = plp->lp_ctUsed*GRENADE_TRAIL_INTERPOSITIONS; + for(INDEX iPos = 1; iPoslp_ctUsed; iPos++) + { + pvPos1 = pvPos2; + pvPos2 = &plp->GetPosition(iPos); + for (INDEX iInter=0; iInterGetLastPositions(CANNON_TRAIL_POSITIONS); +} +void Particles_CannonBall(CEntity *pen, FLOAT fSpeedRatio) +{ + CLastPositions *plp = pen->GetLastPositions(CANNON_TRAIL_POSITIONS); + // FLOAT fSeconds = _pTimer->GetLerpedCurrentTick(); + + Particle_PrepareTexture(&_toCannonBall, PBT_BLEND); + Particle_SetTexturePart( 512, 512, 0, 0); + + FLOAT3D vOldPos = plp->GetPosition(1); + for( INDEX iPos=2; iPoslp_ctUsed; iPos++) + { + FLOAT3D vPos = plp->GetPosition(iPos); + UBYTE ub = UBYTE((255-iPos*256/plp->lp_ctUsed)*fSpeedRatio); + FLOAT fSize = (CANNON_TRAIL_POSITIONS-iPos)*0.04f+0.04f; + Particle_RenderLine( vPos, vOldPos, fSize, RGBToColor(ub,ub,ub)|ub); + vOldPos=vPos; + } + // all done + Particle_Flush(); +} + +#define LAVA_TRAIL_POSITIONS 32 +#define LAVA_TRAIL_INTERPOSITIONS 1 +void Particles_LavaTrail_Prepare(CEntity *pen) +{ + pen->GetLastPositions(LAVA_TRAIL_POSITIONS); +} +void Particles_LavaTrail(CEntity *pen) +{ + CLastPositions *plp = pen->GetLastPositions(LAVA_TRAIL_POSITIONS); + FLOAT fSeconds = _pTimer->GetLerpedCurrentTick(); + + CTextureData *pTD = (CTextureData *) _toLavaTrailGradient.GetData(); + Particle_PrepareTexture(&_toLavaTrailSmoke, PBT_BLEND); + //Particle_PrepareTexture(&_toLavaTrailSmoke, PBT_MULTIPLY); + Particle_SetTexturePart( 512, 512, 0, 0); + + const FLOAT3D *pvPos1; + const FLOAT3D *pvPos2 = &plp->GetPosition(0); + INDEX iParticle = 0; + INDEX iParticlesLiving = plp->lp_ctUsed*LAVA_TRAIL_INTERPOSITIONS; + for(INDEX iPos = 1; iPoslp_ctUsed; iPos++) + { + pvPos1 = pvPos2; + pvPos2 = &plp->GetPosition(iPos); + for (INDEX iInter=0; iInterGetTexel(PIX(FLOAT(iParticle)/iParticlesLiving*8*1024), 0); + Particle_RenderSquare( vPos, fSize, fAngle, col); + iParticle++; + } + } + // all done + Particle_Flush(); +} + +#define LAVA_BOMB_TRAIL_POSITIONS 16 +#define LAVA_BOMB_TRAIL_INTERPOSITIONS 1 +void Particles_LavaBombTrail_Prepare(CEntity *pen) +{ + pen->GetLastPositions(LAVA_BOMB_TRAIL_POSITIONS); +} + +void Particles_LavaBombTrail(CEntity *pen, FLOAT fSizeMultiplier) +{ + CLastPositions *plp = pen->GetLastPositions(LAVA_BOMB_TRAIL_POSITIONS); + FLOAT fSeconds = _pTimer->GetLerpedCurrentTick(); + + CTextureData *pTD = (CTextureData *) _toLavaBombTrailGradient.GetData(); + Particle_PrepareTexture(&_toLavaBombTrailSmoke, PBT_BLEND); + Particle_SetTexturePart( 512, 512, 0, 0); + + const FLOAT3D *pvPos1; + const FLOAT3D *pvPos2 = &plp->GetPosition(0); + INDEX iParticle = 0; + INDEX iParticlesLiving = plp->lp_ctUsed*LAVA_BOMB_TRAIL_INTERPOSITIONS; + for(INDEX iPos = 1; iPoslp_ctUsed; iPos++) + { + INDEX iRnd = ((ULONG)fSeconds+iPos)%CT_MAX_PARTICLES_TABLE; + pvPos1 = pvPos2; + pvPos2 = &plp->GetPosition(iPos); + if( *pvPos1 == *pvPos2) continue; + for (INDEX iInter=0; iInterGetTexel(PIX(FLOAT(iParticle)/iParticlesLiving*8*1024), 0); + Particle_RenderSquare( vPos, fSize, fAngle, col); + iParticle++; + } + } + // all done + Particle_Flush(); +} + +#define BEAST_PROJECTILE_DEBRIS_TRAIL_POSITIONS 8 +#define BEAST_PROJECTILE_DEBRIS_TRAIL_INTERPOSITIONS 1 +void Particles_BeastProjectileDebrisTrail_Prepare(CEntity *pen) +{ + pen->GetLastPositions(BEAST_PROJECTILE_DEBRIS_TRAIL_POSITIONS); +} + +void Particles_BeastProjectileDebrisTrail(CEntity *pen, FLOAT fSizeMultiplier) +{ + CLastPositions *plp = pen->GetLastPositions(BEAST_PROJECTILE_DEBRIS_TRAIL_POSITIONS); + FLOAT fSeconds = _pTimer->GetLerpedCurrentTick(); + + CTextureData *pTD = (CTextureData *) _toBeastDebrisTrailGradient.GetData(); + Particle_PrepareTexture(&_toBeastDebrisTrailTexture, PBT_BLEND); + Particle_SetTexturePart( 512, 512, 0, 0); + + const FLOAT3D *pvPos1; + const FLOAT3D *pvPos2 = &plp->GetPosition(0); + INDEX iParticle = 0; + INDEX iParticlesLiving = plp->lp_ctUsed*BEAST_PROJECTILE_DEBRIS_TRAIL_INTERPOSITIONS; + for(INDEX iPos = 1; iPoslp_ctUsed; iPos++) + { + pvPos1 = pvPos2; + pvPos2 = &plp->GetPosition(iPos); + for (INDEX iInter=0; iInterGetTexel(PIX(FLOAT(iParticle)/iParticlesLiving*8*1024), 0); + Particle_RenderSquare( vPos, fSize, fAngle, col); + iParticle++; + } + } + // all done + Particle_Flush(); +} + +#define BEAST_PROJECTILE_TRAIL_POSITIONS 32 +#define BEAST_PROJECTILE_TRAIL_INTERPOSITIONS 1 +void Particles_BeastProjectileTrail_Prepare(CEntity *pen) +{ + pen->GetLastPositions(BEAST_PROJECTILE_TRAIL_POSITIONS); +} + +#define BEAST_PROJECTILE_LINE_PARTICLES 0.4f +#define BEAST_PROJECTILE_FADE_OUT 0.3f +#define BEAST_PROJECTILE_TOTAL_TIME 0.6f +void Particles_BeastProjectileTrail( CEntity *pen, FLOAT fSize, FLOAT fHeight, INDEX ctParticles) +{ + ASSERT( ctParticles<=CT_MAX_PARTICLES_TABLE); + FLOAT fNow = _pTimer->GetLerpedCurrentTick(); + + Particle_PrepareTexture(&_toBeastProjectileTrailTexture, PBT_BLEND); + Particle_SetTexturePart( 512, 2048, 0, 0); + + CTextureData *pTD = (CTextureData *) _toBeastProjectileTrailGradient.GetData(); + + CPlacement3D pl = pen->GetLerpedPlacement(); + FLOATmatrix3D m; + MakeRotationMatrixFast(m, pl.pl_OrientationAngle); + FLOAT3D vX( m(1,1), m(2,1), m(3,1)); + FLOAT3D vY( -m(1,3), -m(2,3), -m(3,3)); + FLOAT3D vZ( m(1,2), m(2,2), m(3,2)); + FLOAT3D vCenter = pl.pl_PositionVector+vY*fHeight; + + for( INDEX iStar=0; iStar(1.0f-BEAST_PROJECTILE_FADE_OUT)) fFade=(1-fT)*(1/BEAST_PROJECTILE_FADE_OUT); + //else fFade=1.0f; + +#define GET_POS( time) vCenter + \ + vX*(afStarsPositions[iStar][0]*time*fSize*1.5) +\ + vY*(-time*time*10.0f+(afStarsPositions[iStar][1]*2+2.0f)*1.2f*time) +\ + vZ*(afStarsPositions[iStar][2]*time*fSize*1.5); + + FLOAT3D vPos = GET_POS( fT); + COLOR colStar = pTD->GetTexel( FloatToInt(fT*8192), 0); + + if( fT>BEAST_PROJECTILE_LINE_PARTICLES) + { + FLOAT fTimeOld = fT-0.25f; + FLOAT3D vOldPos = GET_POS( fTimeOld); + Particle_RenderLine( vOldPos, vPos, 0.4f, colStar); + } + else + { + Particle_RenderSquare( vPos, 0.5f, fT*360.0f, colStar); + } + } + // all done + Particle_Flush(); +} + +#define BEAST_BIG_PROJECTILE_TRAIL_POSITIONS 32 +#define BEAST_BIG_PROJECTILE_TRAIL_INTERPOSITIONS 1 +void Particles_BeastBigProjectileTrail_Prepare(CEntity *pen) +{ + pen->GetLastPositions(BEAST_BIG_PROJECTILE_TRAIL_POSITIONS); +} + +#define BIG_BEAST_PROJECTILE_LINE_PARTICLES 0.4f +#define BIG_BEAST_PROJECTILE_FADE_OUT 0.4f +#define BIG_BEAST_PROJECTILE_TOTAL_TIME 0.6f +void Particles_BeastBigProjectileTrail( CEntity *pen, FLOAT fSize, FLOAT fZOffset, FLOAT fYOffset, INDEX ctParticles) +{ + ASSERT( ctParticles<=CT_MAX_PARTICLES_TABLE); + FLOAT fNow = _pTimer->GetLerpedCurrentTick(); + + Particle_PrepareTexture(&_toBeastBigProjectileTrailTexture, PBT_BLEND); + Particle_SetTexturePart( 512, 2048, 0, 0); + + CTextureData *pTD = (CTextureData *) _toBeastBigProjectileTrailGradient.GetData(); + + CPlacement3D pl = pen->GetLerpedPlacement(); + FLOATmatrix3D m; + MakeRotationMatrixFast(m, pl.pl_OrientationAngle); + FLOAT3D vX( m(1,1), m(2,1), m(3,1)); + FLOAT3D vY( -m(1,3), -m(2,3), -m(3,3)); + FLOAT3D vZ( m(1,2), m(2,2), m(3,2)); + FLOAT3D vCenter = pl.pl_PositionVector+vY*fZOffset+vZ*fYOffset; + + for( INDEX iStar=0; iStar(1.0f-BIG_BEAST_PROJECTILE_FADE_OUT)) fFade=(1-fT)*(1/BIG_BEAST_PROJECTILE_FADE_OUT); + else fFade=1.0f; + +#define GET_POS_BIG( time) vCenter + \ + vX*(afStarsPositions[iStar][0]*time*fSize*1.5) +\ + vY*(time*time*-15.0f+(afStarsPositions[iStar][1]*2+3.0f)*1.2f*time) +\ + vZ*(afStarsPositions[iStar][2]*time*fSize*1.5); + + FLOAT3D vPos = GET_POS_BIG( fT); + COLOR colStar = pTD->GetTexel( FloatToInt(fT*8192), 0); + + if( fT>BIG_BEAST_PROJECTILE_LINE_PARTICLES) + { + FLOAT fTimeOld = fT-0.125f; + FLOAT3D vOldPos = GET_POS_BIG( fTimeOld); + Particle_RenderLine( vOldPos, vPos, 0.6f*fFade, colStar); + } + else + { + Particle_RenderSquare( vPos, 0.5, fT*360.0f, colStar); + } + } + // all done + Particle_Flush(); +} + +#define ROCKET_TRAIL_POSITIONS 16 +#define ROCKET_TRAIL_INTERPOSITIONS 3 +void Particles_RocketTrail_Prepare(CEntity *pen) +{ + pen->GetLastPositions(ROCKET_TRAIL_POSITIONS); +} +void Particles_RocketTrail(CEntity *pen, FLOAT fStretch) +{ + CLastPositions *plp = pen->GetLastPositions(ROCKET_TRAIL_POSITIONS); + //FLOAT fSeconds = _pTimer->GetLerpedCurrentTick(); + + Particle_PrepareTexture(&_toRocketTrail, PBT_ADD); + Particle_SetTexturePart( 512, 512, 0, 0); + + const FLOAT3D *pvPos1; + const FLOAT3D *pvPos2 = &plp->GetPosition(1); + INDEX iParticle = 0; + INDEX iParticlesLiving = plp->lp_ctUsed*ROCKET_TRAIL_INTERPOSITIONS; + for( INDEX iPos=2; iPoslp_ctUsed; iPos++) + { + pvPos1 = pvPos2; + pvPos2 = &plp->GetPosition(iPos); + if( (*pvPos2 - *pvPos1).Length() == 0.0f) + { + continue; + } + for (INDEX iInter=0; iInterGetPosition(1); + for( INDEX iPos=2; iPoslp_ctUsed; iPos++) + { + FLOAT3D vPos = plp->GetPosition(iPos); + if( (vPos - vOldPos).Length() == 0.0f) + { + continue; + } + UBYTE ub = UBYTE(255-iPos*256/plp->lp_ctUsed); + FLOAT fSize = iPos*0.01f*fStretch+0.005f; + Particle_RenderLine( vPos, vOldPos, fSize, RGBToColor(ub,ub,ub)|ub); + vOldPos=vPos; + } + // all done + Particle_Flush(); +} + + +#define BLOOD01_TRAIL_POSITIONS 15 +void Particles_BloodTrail(CEntity *pen) +{ + // get blood type + const INDEX iBloodType = GetSP()->sp_iBlood; + if( iBloodType<1) return; + COLOR col; + if( iBloodType==3) Particle_PrepareTexture( &_toFlowerSprayTexture, PBT_BLEND); + else Particle_PrepareTexture( &_toBloodSprayTexture, PBT_BLEND); + + CLastPositions *plp = pen->GetLastPositions(BLOOD01_TRAIL_POSITIONS); + FLOAT fGA = ((CMovableEntity *)pen)->en_fGravityA; + FLOAT3D vGDir = ((CMovableEntity *)pen)->en_vGravityDir; + + for( INDEX iPos=0; iPoslp_ctUsed; iPos++) + { + Particle_SetTexturePart( 256, 256, iPos%8, 0); + FLOAT3D vPos = plp->GetPosition(iPos); + //FLOAT fRand = rand()/FLOAT(RAND_MAX); + FLOAT fAngle = iPos*2.0f*PI/BLOOD01_TRAIL_POSITIONS; + //FLOAT fSin = FLOAT(sin(fAngle)); + FLOAT fT = iPos*_pTimer->TickQuantum; + vPos += vGDir*fGA*fT*fT/8.0f; + FLOAT fSize = 0.2f-iPos*0.15f/BLOOD01_TRAIL_POSITIONS; + UBYTE ub = 255-iPos*255/BLOOD01_TRAIL_POSITIONS; + if( iBloodType==3) col = C_WHITE|ub; + else if( iBloodType==2) col = RGBAToColor(ub,20,20,ub); + else col = RGBAToColor(0,ub,0,ub); + Particle_RenderSquare( vPos, fSize, fAngle, col); + } + // all done + Particle_Flush(); +} + + +INDEX Particles_FireBreath(CEntity *pen, FLOAT3D vSource, FLOAT3D vTarget, FLOAT tmStart, FLOAT tmStop) +{ + Particle_PrepareTexture( &_toFlamethrowerTrail, PBT_ADD); + Particle_SetTexturePart( 512, 512, 0, 0); + + FLOAT fNow = _pTimer->GetLerpedCurrentTick(); + FLOAT fFlameLife = 2; + INDEX ctFlames = 32; + INDEX ctRendered = 0; + FLOAT tmFlameDelta = 0.25f; + FLOAT3D vFocus = Lerp( vSource, vTarget, 0.25f); + for( INDEX iFlame=0; iFlamefFlameLife || tmFakeStart>tmStop) continue; + // calculate fraction part + FLOAT fT=fPassedTime/fFlameLife; + fT=fT-INDEX(fT); + // lerp position + FLOAT3D vRnd = FLOAT3D( afStarsPositions[iFlame][0],afStarsPositions[iFlame][1], + afStarsPositions[iFlame][2])*10; + FLOAT3D vPos = Lerp( vSource, vFocus+vRnd, fT); + FLOAT fSize = 5.0f*fT+5.0f; + UBYTE ub = CalculateRatio( fT, 0.0f, 1.0f, 0.1f, 0.2f)*255; + Particle_RenderSquare( vPos, fSize, fT*(1.0f+afStarsPositions[iFlame*3][1])*360.0f, RGBToColor(ub,ub,ub)|0xFF); + ctRendered++; + } + // all done + Particle_Flush(); + return ctRendered; +} + +INDEX Particles_Regeneration(CEntity *pen, FLOAT tmStart, FLOAT tmStop, FLOAT fYFactor, BOOL bDeath) +{ + Particle_PrepareTexture( &_toElectricitySparks, PBT_BLEND); + Particle_SetTexturePart( 512, 1024, 0, 0); + FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector; + + FLOAT fNow = _pTimer->GetLerpedCurrentTick(); + FLOAT fLife = 1.5; + INDEX ctRendered = 0; + FLOAT tmDelta = 0.001f; + for( INDEX iVtx=0; iVtx<1024*4; iVtx++) + { + FLOAT tmFakeStart = tmStart+iVtx*tmDelta; + FLOAT fPassedTime = fNow-tmFakeStart; + if(fPassedTime<0.0f || fPassedTime>fLife || tmFakeStart>tmStop) continue; + // calculate fraction part + FLOAT fT=fPassedTime/fLife; + fT=fT-INDEX(fT); + + INDEX iRnd = iVtx%CT_MAX_PARTICLES_TABLE; + FLOAT3D vRnd= FLOAT3D(afStarsPositions[iRnd][0],afStarsPositions[iRnd][1]+0.5f,afStarsPositions[iRnd][2]); + vRnd(1) *= 800.0f; + vRnd(2) *= 400.0f; + vRnd(3) *= 800.0f; + FLOAT3D vSource = vCenter+vRnd; + FLOAT3D vDestination = vCenter+vRnd*0.05f; + vDestination(2) += 40.0f*fYFactor+vRnd(2)/8.0f*fYFactor; + FLOAT3D vPos, vPos2; + // lerp position + if(bDeath) { + vPos = Lerp( vSource, vDestination, 1.0f-fT); + } else { + vPos = Lerp( vSource, vDestination, fT); + } + FLOAT fT2 = Clamp(fT-0.025f-fT*fT*0.025f, 0.0f, 1.0f); + + if(bDeath) { + vPos2 = Lerp( vSource, vDestination, 1.0f-fT2); + } else { + vPos2 = Lerp( vSource, vDestination, fT2); + } + + UBYTE ubR = 192+afStarsPositions[iRnd][0]*64; + UBYTE ubG = 192+afStarsPositions[iRnd][1]*64; + UBYTE ubB = 192+afStarsPositions[iRnd][2]*64; + UBYTE ubA = CalculateRatio( fT, 0.0f, 1.0f, 0.4f, 0.01f)*255; + COLOR colLine = RGBToColor( ubR, ubG, ubB) | ubA; + + FLOAT fSize = 1.0f; + Particle_RenderLine( vPos2, vPos, fSize, colLine); + ctRendered++; + } + + // flush array + avVertices.PopAll(); + // all done + Particle_Flush(); + return ctRendered; +} + +#define SECONDS_PER_PARTICLE 0.01f +void Particles_FlameThrower(const CPlacement3D &plEnd, const CPlacement3D &plStart, + FLOAT fEndElapsed, FLOAT fStartElapsed) +{ + Particle_PrepareTexture( &_toFlamethrowerTrail, PBT_ADD); + Particle_SetTexturePart( 512, 512, 0, 0); + + const FLOAT3D &vStart = plStart.pl_PositionVector; + const FLOAT3D &vEnd = plEnd.pl_PositionVector; + FLOAT3D vDelta = (vEnd-vStart)/(fEndElapsed-fStartElapsed); + FLOAT fSeconds = _pTimer->GetLerpedCurrentTick(); + + for(FLOAT fTime = ceil(fStartElapsed/SECONDS_PER_PARTICLE)*SECONDS_PER_PARTICLE; + fTime0.75f) ub = 0; + else if( fTime>0.5f) ub = (-4*fTime+3)*96; + + ASSERT(fTime>=0.0f); + ASSERT(fSize>=0.0f); + FLOAT3D vPos = vStart+vDelta*(fTime-fStartElapsed)+FLOAT3D(0.0f, fRise, 0.0f); + Particle_RenderSquare( vPos, fSize, fAngle, RGBToColor(ub,ub,ub)|0xFF); + } + // all done + Particle_Flush(); +} + +void SetupParticleTexture(enum ParticleTexture ptTexture) +{ + switch(ptTexture) { + case PT_STAR01: Particle_PrepareTexture(&_toStar01, PBT_ADD); break; + case PT_STAR02: Particle_PrepareTexture(&_toStar02, PBT_ADD); break; + case PT_STAR03: Particle_PrepareTexture(&_toStar03, PBT_ADD); break; + case PT_STAR04: Particle_PrepareTexture(&_toStar04, PBT_ADD); break; + case PT_STAR05: Particle_PrepareTexture(&_toStar05, PBT_ADD); break; + case PT_STAR06: Particle_PrepareTexture(&_toStar06, PBT_ADD); break; + case PT_STAR07: Particle_PrepareTexture(&_toStar07, PBT_ADD); break; + case PT_STAR08: Particle_PrepareTexture(&_toStar08, PBT_ADD); break; + case PT_BOUBBLE01: Particle_PrepareTexture(&_toBoubble01, PBT_ADD); break; + case PT_BOUBBLE02: Particle_PrepareTexture(&_toBoubble02, PBT_ADD); break; + case PT_WATER01: Particle_PrepareTexture(&_toBoubble03, PBT_BLEND); break; + case PT_WATER02: Particle_PrepareTexture(&_toBoubble03, PBT_BLEND); break; + case PT_SANDFLOW: Particle_PrepareTexture(&_toSand, PBT_BLEND); break; + case PT_WATERFLOW: Particle_PrepareTexture(&_toWater, PBT_BLEND); break; + case PT_LAVAFLOW: Particle_PrepareTexture(&_toLava, PBT_BLEND); break; + default: ASSERT(FALSE); + } + Particle_SetTexturePart( 512, 512, 0, 0); +} + +void InitParticleTables(void) +{ + for( INDEX iStar=0; iStar7.0f) return; + + FLOAT fNow = _pTimer->GetLerpedCurrentTick(); + SetupParticleTexture( ptTexture); + const FLOATmatrix3D &m = pen->GetRotationMatrix(); + FLOAT3D vY( m(1,2), m(2,2), m(3,2)); + CPlacement3D plSource = pen->GetLerpedPlacement(); + FLOAT3D vCenter = plSource.pl_PositionVector+vY*fHeight; + + for( INDEX iStar=0; iStarSTARDUST_EXIST_TIME) continue; + FLOAT fFade = -2.0f * Abs(fT*(1.0f/STARDUST_EXIST_TIME)-0.5f)+1.0f; + + INDEX iRandomFromPlacement = + (ULONG)(plSource.pl_PositionVector(1)+plSource.pl_PositionVector(3))&(ctOffsetSpace-1); + INDEX iMemeber = iStar+iRandomFromPlacement; + const FLOAT3D vPos = vCenter+FLOAT3D( afStarsPositions[iMemeber][0], + afStarsPositions[iMemeber][1], + afStarsPositions[iMemeber][2])*fSize; + COLOR colStar = RGBToColor( auStarsColors[iMemeber][0]*fFade, + auStarsColors[iMemeber][1]*fFade, + auStarsColors[iMemeber][2]*fFade); + Particle_RenderSquare( vPos, 0.15f, 0, colStar|0xFF); + } + // all done + Particle_Flush(); +} + +#define RISING_TOTAL_TIME 5.0f +#define RISING_EXIST_TIME 3.0f +#define RISING_FADE_IN 0.3f +#define RISING_FADE_OUT 0.3f + +void Particles_Rising(CEntity *pen, FLOAT fStartTime, FLOAT fStopTime, FLOAT fStretchAll, + FLOAT fStretchX, FLOAT fStretchY, FLOAT fStretchZ, FLOAT fSize, + enum ParticleTexture ptTexture, INDEX ctParticles) +{ + ASSERT( ctParticles<=CT_MAX_PARTICLES_TABLE); + if( Particle_GetMipFactor()>7.0f) return; + + FLOAT fNow = _pTimer->GetLerpedCurrentTick(); + SetupParticleTexture( ptTexture); + const FLOATmatrix3D &m = pen->GetRotationMatrix(); + FLOAT3D vY( m(1,2), m(2,2), m(3,2)); + FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector+vY*fStretchY; + + FLOAT fPowerFactor = Clamp((fNow - fStartTime)/5.0f,0.0f,1.0f); + fPowerFactor *= Clamp(1+(fStopTime-fNow)/5.0f,0.0f,1.0f); + //ctParticles = FLOAT(ctParticles) * fPowerFactor; + + for( INDEX iStar=0; iStar1) continue; + FLOAT fFade; + if(fF<(RISING_FADE_IN*fPowerFactor)) fFade=fF*(1/(RISING_FADE_IN*fPowerFactor)); + else if (fF>(1.0f-RISING_FADE_OUT)) fFade=(1-fF)*(1/RISING_FADE_OUT); + else fFade=1.0f; + + FLOAT3D vPos = vCenter+FLOAT3D( + afStarsPositions[iStar][0]*fStretchX, + afStarsPositions[iStar][1]*fStretchY, + afStarsPositions[iStar][2]*fStretchZ)*fStretchAll+vY*(fF*fStretchAll*0.5f); + vPos(1)+=sin(fF*4.0f)*0.05f*fStretchAll; + vPos(3)+=cos(fF*4.0f)*0.05f*fStretchAll; + + UBYTE ub = NormFloatToByte( fFade); + COLOR colStar = RGBToColor( ub, ub, ub>>1); + Particle_RenderSquare( vPos, fSize*fPowerFactor, 0, colStar|(UBYTE(0xFF*fPowerFactor))); + } + // all done + Particle_Flush(); +} + +#define CT_SPIRAL_PARTICLES 4 +#define CT_SPIRAL_TRAIL 10 +void Particles_Spiral( CEntity *pen, FLOAT fSize, FLOAT fHeight, + enum ParticleTexture ptTexture, INDEX ctParticles) +{ + ASSERT( ctParticles<=CT_MAX_PARTICLES_TABLE); + + FLOAT fMipFactor = Particle_GetMipFactor(); + if( fMipFactor>7.0f) return; + fMipFactor = 2.5f-fMipFactor*0.3f; + fMipFactor = Clamp( fMipFactor, 0.0f, 1.0f); + INDEX ctSpiralTrail = fMipFactor*CT_SPIRAL_TRAIL; + if( ctSpiralTrail<=0) return; + FLOAT fTrailDelta = 0.1f/fMipFactor; + + FLOAT fNow = _pTimer->GetLerpedCurrentTick(); + SetupParticleTexture( ptTexture); + const FLOATmatrix3D &m = pen->GetRotationMatrix(); + FLOAT3D vY( m(1,2), m(2,2), m(3,2)); + FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector+vY*fHeight; + + for( INDEX iStar=0; iStar>1); + Particle_RenderSquare( vPos, 0.2f, 0, colStar|0xFF); + } + } + // all done + Particle_Flush(); +} + +#define EMANATE_FADE_IN 0.2f +#define EMANATE_FADE_OUT 0.6f +#define EMANATE_TOTAL_TIME 1.0f +#define EMANATE_EXIST_TIME 0.5f +void Particles_Emanate( CEntity *pen, FLOAT fSize, FLOAT fHeight, + enum ParticleTexture ptTexture, INDEX ctParticles) +{ + ASSERT( ctParticles<=CT_MAX_PARTICLES_TABLE); + if( Particle_GetMipFactor()>7.0f) return; + + FLOAT fNow = _pTimer->GetLerpedCurrentTick(); + SetupParticleTexture( ptTexture); + const FLOATmatrix3D &m = pen->GetRotationMatrix(); + FLOAT3D vY( m(1,2), m(2,2), m(3,2)); + FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector+vY*fHeight; + + for( INDEX iStar=0; iStar1) continue; + FLOAT fFade; + if(fF(1.0f-EMANATE_FADE_OUT)) fFade=(1-fF)*(1/EMANATE_FADE_OUT); + else fFade=1.0f; + + FLOAT3D vPos = vCenter+FLOAT3D( + afStarsPositions[iStar][0], + afStarsPositions[iStar][1], + afStarsPositions[iStar][2])*fSize*(fF+0.4f); + + UBYTE ub = NormFloatToByte( fFade); + COLOR colStar = RGBToColor( ub, ub, ub>>1); + Particle_RenderSquare( vPos, 0.1f, 0, colStar|0xFF); + } + // all done + Particle_Flush(); +} + +#define WATERFALL_FOAM_FADE_IN 0.1f +#define WATERFALL_FOAM_FADE_OUT 0.4f +void Particles_WaterfallFoam(CEntity *pen, FLOAT fSizeX, FLOAT fSizeY, FLOAT fSizeZ, + FLOAT fParticleSize, FLOAT fSpeed, FLOAT fSpeedY, FLOAT fLife, INDEX ctParticles) +{ + if(fLife<=0) return; + + Particle_PrepareTexture( &_toWaterfallFoam, PBT_ADD); + Particle_SetTexturePart( 512, 512, 0, 0); + + FLOAT fNow = _pTimer->GetLerpedCurrentTick(); + const FLOATmatrix3D &m = pen->GetRotationMatrix(); + FLOAT3D vX( m(1,1), m(2,1), m(3,1)); + FLOAT3D vY( m(1,2), m(2,2), m(3,2)); + FLOAT3D vZ( m(1,3), m(2,3), m(3,3)); + FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector; + + for( INDEX iFoam=0; iFoam7.0f) return; + + FLOAT fNow = _pTimer->GetLerpedCurrentTick(); + SetupParticleTexture( ptTexture); + const FLOATmatrix3D &m = pen->GetRotationMatrix(); + FLOAT3D vX( m(1,1), m(2,1), m(3,1)); + FLOAT3D vY( m(1,2), m(2,2), m(3,2)); + FLOAT3D vZ( m(1,3), m(2,3), m(3,3)); + FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector; + + for( INDEX iStar=0; iStar1) continue; + FLOAT fFade; + if(fF(1.0f-EMANATE_FADE_OUT)) fFade=(1-fF)*(1/EMANATE_FADE_OUT); + else fFade=1.0f; + + FLOAT fX = (afStarsPositions[iStar][0]+0.5f)*fSizeX*(1+fF*fAway); + FLOAT fY = fSizeY*fF; + FLOAT fZ = (afStarsPositions[iStar][2]+0.5f)*fSizeZ*(1+fF*fAway); + FLOAT3D vPos = vCenter + vX*fX + vY*fY + vZ*fZ; + + UBYTE ub = NormFloatToByte( fFade); + COLOR colStar = RGBToColor( ub, ub, ub); + Particle_RenderSquare( vPos, fParticleSize, 0, colStar|0xFF); + } + // all done + Particle_Flush(); +} + +#define CT_FOUNTAIN_TRAIL 3 +#define FOUNTAIN_FADE_IN 0.6f +#define FOUNTAIN_FADE_OUT 0.4f +#define FOUNTAIN_TOTAL_TIME 0.6f +void Particles_Fountain( CEntity *pen, FLOAT fSize, FLOAT fHeight, + enum ParticleTexture ptTexture, INDEX ctParticles) +{ + ASSERT( ctParticles<=CT_MAX_PARTICLES_TABLE); + FLOAT fNow = _pTimer->GetLerpedCurrentTick(); + + SetupParticleTexture( ptTexture); + CTextureData *pTD = (CTextureData *) _toWaterfallGradient.GetData(); + const FLOATmatrix3D &m = pen->GetRotationMatrix(); + FLOAT3D vX( m(1,1), m(2,1), m(3,1)); + FLOAT3D vY( m(1,2), m(2,2), m(3,2)); + FLOAT3D vZ( m(1,3), m(2,3), m(3,3)); + FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector+vY*fHeight; + + for( INDEX iStar=0; iStar(1.0f-FOUNTAIN_FADE_OUT)) fFade=(1-fT)*(1/FOUNTAIN_FADE_OUT); + else fFade=1.0f; + fFade *= (CT_FOUNTAIN_TRAIL-iTrail)*(1.0f/CT_FOUNTAIN_TRAIL); + + FLOAT3D vPos = vCenter + + vX*(afStarsPositions[iStar][0]*fT*fSize) + + vY*(fT*fT*-5.0f+(afStarsPositions[iStar][1]*2+4.0f)*1.2f*fT) + + vZ*(afStarsPositions[iStar][2]*fT*fSize); + + COLOR colStar = pTD->GetTexel( FloatToInt(fFade*2048), 0); + ULONG ulA = FloatToInt( ((colStar&CT_AMASK)>>CT_ASHIFT) * fFade); + colStar = (colStar&~CT_AMASK) | (ulA<en_ulID)%CT_MAX_PARTICLES_TABLE; + Particle_SetTexturePart( 512, 512, iRnd1%3, 0); + + FLOAT fT = _pTimer->GetLerpedCurrentTick()-tmStarted; + FLOAT fBoxSize = boxOwner.Size().Length(); + for(INDEX iSmoke=0; iSmoke<2+fDamage*2; iSmoke++) + { + INDEX iRnd2 = INDEX(tmStarted*12345.0f+iSmoke+fDamage*10.0f)%(CT_MAX_PARTICLES_TABLE/2); + FLOAT fLifeTime = 2.0f+(afStarsPositions[iRnd2][0]+0.5f)*2.0f; + FLOAT fRatio = CalculateRatio(fT, 0, fLifeTime, 0.4f, 0.6f); + + FLOAT fRndAppearX = afStarsPositions[iRnd2][0]*fBoxSize*0.125f; + FLOAT fRndAppearZ = afStarsPositions[iRnd2][2]*fBoxSize*0.125f; + FLOAT3D vPos = pen->GetLerpedPlacement().pl_PositionVector; + vPos(1) += fRndAppearX; + vPos(3) += fRndAppearZ; + vPos(2) += ((afStarsPositions[iRnd2+4][1]+0.5f)*2.0f+1.5f)*fT+boxOwner.Size()(2)*0.0025f; + + COLOR col = C_dGRAY|UBYTE(64.0f*fRatio); + FLOAT fRotation = afStarsPositions[iRnd2+5][0]*360+fT*200.0f*afStarsPositions[iRnd2+3][0]; + FLOAT fSize = + 0.025f*fDamage+ + (afStarsPositions[iRnd2+6][2]+0.5f)*0.075 + + (0.15f+(afStarsPositions[iRnd2+2][1]+0.5f)*0.075f*fBoxSize)*fT; + Particle_RenderSquare( vPos, fSize, fRotation, col); + } + + // all done + Particle_Flush(); +} + +#define RUNNING_DUST_TRAIL_POSITIONS 3*20 +void Particles_RunningDust_Prepare(CEntity *pen) +{ + pen->GetLastPositions(RUNNING_DUST_TRAIL_POSITIONS); +} +void Particles_RunningDust(CEntity *pen) +{ + Particle_PrepareTexture( &_toBulletSmoke, PBT_BLEND); + CLastPositions *plp = pen->GetLastPositions(RUNNING_DUST_TRAIL_POSITIONS); + FLOAT3D vOldPos = plp->GetPosition(1); + for(INDEX iPos = 2; iPoslp_ctUsed; iPos++) + { + FLOAT3D vPos = plp->GetPosition(iPos); + if( (vPos-vOldPos).Length()<1.0f) continue; + FLOAT tmStarted = _pTimer->CurrentTick()-iPos*_pTimer->TickQuantum; + INDEX iRnd = INDEX(Abs(vPos(1)*1234.234f+vPos(2)*9834.123f+vPos(3)*543.532f+pen->en_ulID))%(CT_MAX_PARTICLES_TABLE/2); + if( iRnd&3) continue; + + INDEX iRndTex = iRnd*324561+pen->en_ulID; + Particle_SetTexturePart( 512, 512, iRndTex%3, 0); + + FLOAT fLifeTime = 2.8f-(afStarsPositions[iRnd][1]+0.5f)*1.0f; + + FLOAT fT = _pTimer->GetLerpedCurrentTick()-tmStarted; + FLOAT fRatio = CalculateRatio(fT, 0, fLifeTime, 0.1f, 0.25f); + + FLOAT fRndAppearX = afStarsPositions[iRnd][0]*1.0f; + FLOAT fRndSpeedY = (afStarsPositions[iRnd][1]+0.5f)*0.5f; + FLOAT fRndAppearZ = afStarsPositions[iRnd][2]*1.0f; + vPos(1) += fRndAppearX; + vPos(2) += (0.5f+fRndSpeedY)*fT; + vPos(3) += fRndAppearZ; + + FLOAT fRndBlend = 8.0f+(afStarsPositions[iRnd*2][1]+0.5f)*64.0f; + UBYTE ubRndH = UBYTE( (afStarsPositions[iRnd][0]+0.5f)*64); + UBYTE ubRndS = UBYTE( (afStarsPositions[iRnd][1]+0.5f)*32); + UBYTE ubRndV = UBYTE( 128+afStarsPositions[iRnd][0]*64.0f); + COLOR col = HSVToColor(ubRndH,ubRndS,ubRndV)|UBYTE(fRndBlend*fRatio); + //col=C_RED|CT_OPAQUE; + FLOAT fRotation = afStarsPositions[iRnd+5][0]*360+fT*50.0f*afStarsPositions[iRnd+3][0]; + FLOAT fSize = + 0.75f+(afStarsPositions[iRnd+6][2]+0.5f)*0.25 + // static size + (0.4f+(afStarsPositions[iRnd+2][1]+0.5f)*0.4f)*fT; // dinamic size + Particle_RenderSquare( vPos, fSize, fRotation, col); + vOldPos=vPos; + } + // all done + Particle_Flush(); +} + +void Particles_MetalParts( CEntity *pen, FLOAT tmStarted, FLOATaabbox3D boxOwner, FLOAT fDamage) +{ + Particle_PrepareTexture( &_toMetalSprayTexture, PBT_BLEND); + FLOAT fT = _pTimer->GetLerpedCurrentTick()-tmStarted; + FLOAT fGA = 30.0f; + + FLOAT fBoxSize = boxOwner.Size().Length(); + for(INDEX iPart=0; iPart<6+fDamage*3.0f; iPart++) + { + INDEX iRnd = INDEX(tmStarted*12345.0f+iPart)%CT_MAX_PARTICLES_TABLE; + FLOAT fLifeTime = 2.0f+(afStarsPositions[iRnd][0]+0.5f)*2.0f; + FLOAT fRatio = CalculateRatio(fT, 0, fLifeTime, 0.1f, 0.1f); + Particle_SetTexturePart( 256, 256, ((int(tmStarted*100.0f))%8+iPart)%8, 0); + + FLOAT3D vPos = pen->GetLerpedPlacement().pl_PositionVector; + vPos(1) += afStarsPositions[iRnd][0]*fT*15; + vPos(2) += afStarsPositions[iRnd][1]*fT*15-fGA/2.0f*fT*fT+boxOwner.Size()(2)*0.25f; + vPos(3) += afStarsPositions[iRnd][2]*fT*15; + + UBYTE ubRndH = UBYTE( 180+afStarsPositions[ int(iPart+tmStarted*10)%CT_MAX_PARTICLES_TABLE][0]*16); + UBYTE ubRndS = UBYTE( 12+(afStarsPositions[ int(iPart+tmStarted*10)%CT_MAX_PARTICLES_TABLE][1])*8); + //ubRndS = 0; + UBYTE ubRndV = 255; + COLOR col = HSVToColor(ubRndH, ubRndS, ubRndV)|UBYTE(255.0f*fRatio); + FLOAT fRotation = fT*400.0f*afStarsPositions[iRnd][0]; + FLOAT fSize = fBoxSize*0.005f+0.125f+afStarsPositions[iRnd][1]*0.025f; + Particle_RenderSquare( vPos, fSize, fRotation, col); + } + + // all done + Particle_Flush(); +} + +#define ELECTRICITY_SPARKS_FADE_OUT_TIME 0.4f +#define ELECTRICITY_SPARKS_TOTAL_TIME 1.0f +void Particles_ElectricitySparks( CEntity *pen, FLOAT fTimeAppear, FLOAT fSize, FLOAT fHeight, INDEX ctParticles) +{ + ASSERT( ctParticles<=CT_MAX_PARTICLES_TABLE/2); + FLOAT fT = _pTimer->GetLerpedCurrentTick()-fTimeAppear; + + Particle_PrepareTexture( &_toElectricitySparks, PBT_BLEND); + Particle_SetTexturePart( 512, 1024, 0, 0); + + const FLOATmatrix3D &m = pen->GetRotationMatrix(); + FLOAT3D vX( m(1,1), m(2,1), m(3,1)); + FLOAT3D vY( m(1,2), m(2,2), m(3,2)); + FLOAT3D vZ( m(1,3), m(2,3), m(3,3)); + FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector+vY*fHeight; + + for( INDEX iSpark=0; iSparkELECTRICITY_SPARKS_TOTAL_TIME) + { + fFade=0; + } + else if(fT>ELECTRICITY_SPARKS_FADE_OUT_TIME) + { + fFade=-1.0f/(ELECTRICITY_SPARKS_TOTAL_TIME-ELECTRICITY_SPARKS_FADE_OUT_TIME)*(fT-ELECTRICITY_SPARKS_TOTAL_TIME); + } + else + { + fFade=1.0f; + } + + FLOAT fTold = fT-0.05f; + +#define SPARK_CURVE( time) \ + vCenter + \ + vX*(afStarsPositions[iSpark][0]*time*fSize*3) + \ + vY*(afStarsPositions[iSpark][1]*10.0f*time-(15.0f+afStarsPositions[iSpark*2][1]*15.0f)*time*time) + \ + vZ*(afStarsPositions[iSpark][2]*time*fSize*3); + + FLOAT3D vPosOld = SPARK_CURVE( fTold); + FLOAT3D vPosNew = SPARK_CURVE( fT); + + UBYTE ubR = 224+(afStarsPositions[iSpark][2]+0.5f)*32; + UBYTE ubG = 224+(afStarsPositions[iSpark][2]+0.5f)*32; + UBYTE ubB = 160; + UBYTE ubA = FloatToInt( 255 * fFade); + COLOR colStar = RGBToColor( ubR, ubG, ubB) | ubA; + Particle_RenderLine( vPosOld, vPosNew, 0.075f, colStar); + } + // all done + Particle_Flush(); +} + +void Particles_LavaErupting(CEntity *pen, FLOAT fStretchAll, FLOAT fSize, + FLOAT fStretchX, FLOAT fStretchY, FLOAT fStretchZ, + FLOAT fActivateTime) +{ + FLOAT fT = _pTimer->GetLerpedCurrentTick()-fActivateTime; + if( fT>10.0f) return; + + Particle_PrepareTexture( &_toLavaEruptingTexture, PBT_ADD); + INDEX iTexture = ((ULONG)fActivateTime)%3; + Particle_SetTexturePart( 512, 512, iTexture, 0); + FLOAT fGA = ((CMovableEntity *)pen)->en_fGravityA; + + INDEX iRnd1 = ((ULONG)fActivateTime)%CT_MAX_PARTICLES_TABLE; + INDEX iRnd2 = (~(ULONG)fActivateTime)%CT_MAX_PARTICLES_TABLE; + + FLOAT fRndAppearX = afStarsPositions[iRnd2][0]*fStretchAll; + FLOAT fRndAppearZ = afStarsPositions[iRnd2][1]*fStretchAll; + FLOAT fRndRotation = afStarsPositions[iRnd2][2]; + + FLOAT3D vPos = pen->GetLerpedPlacement().pl_PositionVector; + vPos(1) += fRndAppearX+afStarsPositions[iRnd1][0]*fT*fStretchX*10; + vPos(2) += (fStretchY+(fStretchY*0.25f*afStarsPositions[iRnd1][1]))*fT-fGA/2.0f*fT*fT; + vPos(3) += fRndAppearZ+afStarsPositions[iRnd1][2]*fT*fStretchZ*10; + + Particle_RenderSquare( vPos, fSize+afStarsPositions[iRnd2][2]*fSize*0.5f, fRndRotation*300*fT, C_WHITE|CT_OPAQUE); + + // all done + Particle_Flush(); +} + +#define CT_ATOMIC_TRAIL 32 +void Particles_Atomic( CEntity *pen, FLOAT fSize, FLOAT fHeight, + enum ParticleTexture ptTexture, INDEX ctEllipses) +{ + ASSERT( ctEllipses<=CT_MAX_PARTICLES_TABLE); + FLOAT fMipFactor = Particle_GetMipFactor(); + if( fMipFactor>7.0f) return; + fMipFactor = 2.5f-fMipFactor*0.3f; + fMipFactor = Clamp(fMipFactor, 0.0f ,1.0f); + INDEX ctAtomicTrail = fMipFactor*CT_ATOMIC_TRAIL; + if( ctAtomicTrail<=0) return; + FLOAT fTrailDelta = 0.075f/fMipFactor; + + FLOAT fNow = _pTimer->GetLerpedCurrentTick(); + SetupParticleTexture( ptTexture); + const FLOATmatrix3D &m = pen->GetRotationMatrix(); + FLOAT3D vX( m(1,1), m(2,1), m(3,1)); + FLOAT3D vY( m(1,2), m(2,2), m(3,2)); + FLOAT3D vZ( m(1,3), m(2,3), m(3,3)); + FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector+vY*fHeight; + + for( INDEX iEllipse=0; iEllipse>3, ub>>3, ub>>2); + Particle_RenderSquare( vPos, 0.2f, 0, colStar|0xFF); + } + } + // all done + Particle_Flush(); +} + +#define CT_LIGHTNINGS 8 +void Particles_Ghostbuster(const FLOAT3D &vSrc, const FLOAT3D &vDst, INDEX ctRays, FLOAT fSize, FLOAT fPower, + FLOAT fKneeDivider/*=33.3333333f*/) +{ + Particle_PrepareTexture(&_toGhostbusterBeam, PBT_ADD); + Particle_SetTexturePart( 512, 512, 0, 0); + // get direction vector + FLOAT3D vZ = vDst-vSrc; + FLOAT fLen = vZ.Length(); + vZ.Normalize(); + + // get two normal vectors + FLOAT3D vX; + if (Abs(vZ(2))>0.5) { + vX = FLOAT3D(1.0f, 0.0f, 0.0f)*vZ; + } else { + vX = FLOAT3D(0.0f, 1.0f, 0.0f)*vZ; + } + FLOAT3D vY = vZ*vX; + const FLOAT fStep = fLen/fKneeDivider; + + for(INDEX iRay = 0; iRayGetLerpedCurrentTick()/1.5f; + FLOAT fDT = fT-INDEX(fT); + FLOAT fFade = 1-fDT*4.0f; + + if( fFade>1 || fFade<=0) continue; + UBYTE ubFade = NormFloatToByte(fFade*fPower); + COLOR colFade = RGBToColor( ubFade, ubFade, ubFade); + for(FLOAT fPos=fStep; fPosGetLerpedPlacement().pl_PositionVector; + + vPos(1) -= fGridSize*ctGrids/2; + vPos(3) -= fGridSize*ctGrids/2; + + SnapFloat( vPos(1), fGridSize); + SnapFloat( vPos(2), fGridSize); + SnapFloat( vPos(3), fGridSize); + FLOAT fNow = _pTimer->GetLerpedCurrentTick(); + + Particle_PrepareTexture(&_toRaindrop, PBT_BLEND); + Particle_SetTexturePart( 512, 4096, 0, 0); + + FLOAT fMinX = boxRainMap.Min()(1); + FLOAT fMinY = boxRainMap.Min()(2); + FLOAT fMinZ = boxRainMap.Min()(3); + FLOAT fSizeX = boxRainMap.Size()(1); + FLOAT fSizeY = boxRainMap.Size()(2); + FLOAT fSizeZ = boxRainMap.Size()(3); + PIX pixRainMapW = 1; + PIX pixRainMapH = 1; + + if( ptdRainMap != NULL) + { + pixRainMapW = ptdRainMap->GetPixWidth(); + pixRainMapH = ptdRainMap->GetPixHeight(); + } + + //INDEX ctDiscarded=0; + for( INDEX iZ=0; iZ=0 && pixX=0 && pixZGetTexel( pixX, pixZ); + FLOAT fRainMapY = fMinY+((col>>8)&0xFF)/255.0f*fSizeY; + + FLOAT fRainY = vRender(2); + // if tested raindrop is below ceiling + if( fRainY<=fRainMapY) + { + // don't render it + continue; + } else if (fRainY-fSizeGetLerpedPlacement().pl_PositionVector; + + vPos(1) -= fGridSize*ctGrids/2; + vPos(3) -= fGridSize*ctGrids/2; + + SnapFloat( vPos(1), fGridSize); + SnapFloat( vPos(2), fGridSize); + SnapFloat( vPos(3), fGridSize); + FLOAT fNow = _pTimer->GetLerpedCurrentTick(); + + Particle_PrepareTexture(&_toSnowdrop, PBT_BLEND); + Particle_SetTexturePart( 512, 512, 0, 0); + + for( INDEX iZ=0; iZ0.5) + { + vX = FLOAT3D(1.0f, 0.0f, 0.0f)*vZ; + } + else + { + vX = FLOAT3D(0.0f, 1.0f, 0.0f)*vZ; + } + // we found ortonormal vectors + FLOAT3D vY = vZ*vX; + + FLOAT fAllowRnd = 4.0f/fRandomDivider; + fRandomDivider+=1.0f; + vRenderDest = vSrc+ + vZ*fKneeLen + + vX*(fAllowRnd*afStarsPositions[iRnd][0]*fKneeLen) + + vY*(fAllowRnd*afStarsPositions[iRnd][1]*fKneeLen); + // get new rnd index + iRnd = (iRnd+1) % CT_MAX_PARTICLES_TABLE; + // see if we will spawn new branch of lightning + FLOAT fRnd = ((1-ctBranches/ctMaxBranches)*ctKnees)*afStarsPositions[iRnd][0]; + if( (fRnd < 2.0f) && (fPower>0.25f) ) + { + ctBranches++; + FLOAT3D vNewDirection = (vRenderDest-vSrc).Normalize(); + FLOAT3D vNewDst = vSrc + vNewDirection*fLen; + // recurse into new branch + RenderOneLightningBranch( vSrc, vNewDst, fPath, fTimeStart, fTimeNow, fPower/3.0f, iRnd); + } + } + + // calculate color + UBYTE ubA = UBYTE(fPower*255*fTimeKiller); + // render line + Particle_RenderLine( vSrc, vRenderDest, fPower*2, C_WHITE|ubA); + // add traveled path + fPath += (vRenderDest-vSrc).Length(); + if( fPath/LIGHTNING_SPEED > fPassedTime) + { + bRenderInProgress = FALSE; + } + vSrc = vRenderDest; + } +} + +void Particles_Lightning( FLOAT3D vSrc, FLOAT3D vDst, FLOAT fTimeStart) +{ + Particle_PrepareTexture(&_toLightning, PBT_ADDALPHA); + Particle_SetTexturePart( 512, 512, 0, 0); + + FLOAT fTimeNow = _pTimer->GetLerpedCurrentTick(); + // get rnd index + INDEX iRnd = (INDEX( fTimeStart*100))%CT_MAX_PARTICLES_TABLE; + RenderOneLightningBranch( vSrc, vDst, 0, fTimeStart, fTimeNow, 1.0f, iRnd); + + // all done + Particle_Flush(); +} + +#define CT_SANDFLOW_TRAIL 3 +#define SANDFLOW_FADE_OUT 0.25f +#define SANDFLOW_TOTAL_TIME 1.0f +void Particles_SandFlow( CEntity *pen, FLOAT fStretchAll, FLOAT fSize, FLOAT fHeight, FLOAT fStartTime, FLOAT fStopTime, + INDEX ctParticles) +{ + ASSERT( ctParticles<=CT_MAX_PARTICLES_TABLE); + FLOAT fNow = _pTimer->GetLerpedCurrentTick(); + + SetupParticleTexture( PT_SANDFLOW); + CTextureData *pTD = (CTextureData *) _toSandFlowGradient.GetData(); + const FLOATmatrix3D &m = pen->GetRotationMatrix(); + FLOAT3D vX( m(1,1), m(2,1), m(3,1)); + FLOAT3D vY( m(1,2), m(2,2), m(3,2)); + FLOAT3D vZ( m(1,3), m(2,3), m(3,3)); + FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector; + + FLOAT fPowerFactor = Clamp((fNow - fStartTime)/2.0f,0.0f,1.0f); + fPowerFactor *= Clamp(1+(fStopTime-fNow)/2.0f,0.0f,1.0f); + ctParticles = FLOAT(ctParticles) * fPowerFactor; + fHeight *= fPowerFactor; + for( INDEX iStar=0; iStarfStopTime+2.0f) ) continue; + FLOAT fFade; + if (fT>(1.0f-SANDFLOW_FADE_OUT)) fFade=(1-fT)*(1/SANDFLOW_FADE_OUT); + else fFade=1.0f; + fFade *= (CT_SANDFLOW_TRAIL-iTrail)*(1.0f/CT_SANDFLOW_TRAIL); + + FLOAT3D vPos = vCenter + + vX*(afStarsPositions[iStar][0]*fStretchAll*fPowerFactor+fHeight*fT) + + vY*(fT*fT*-5.0f+(afStarsPositions[iStar][1]*fPowerFactor*0.1)) + + vZ*(afStarsPositions[iStar][2]*fPowerFactor*fT*fStretchAll); + + COLOR colSand = pTD->GetTexel( FloatToInt(fT*2048), 0); + ULONG ulA = FloatToInt( ((colSand&CT_AMASK)>>CT_ASHIFT) * fFade); + colSand = (colSand&~CT_AMASK) | (ulA<GetLerpedCurrentTick(); + + SetupParticleTexture( PT_WATERFLOW); + CTextureData *pTD = (CTextureData *) _toWaterFlowGradient.GetData(); + const FLOATmatrix3D &m = pen->GetRotationMatrix(); + FLOAT3D vX( m(1,1), m(2,1), m(3,1)); + FLOAT3D vY( m(1,2), m(2,2), m(3,2)); + FLOAT3D vZ( m(1,3), m(2,3), m(3,3)); + FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector; + + FLOAT fPowerFactor = Clamp((fNow - fStartTime)/2.0f,0.0f,1.0f); + fPowerFactor *= Clamp(1+(fStopTime-fNow)/2.0f,0.0f,1.0f); + ctParticles = FLOAT(ctParticles) * fPowerFactor; + fHeight *= fPowerFactor; + for( INDEX iStar=0; iStarfStopTime+2.0f) ) continue; + FLOAT fFade; + if (fT>(1.0f-WATER_FLOW_FADE_OUT)) fFade=(1-fT)*(1/WATER_FLOW_FADE_OUT); + else fFade=1.0f; + fFade *= (CT_WATER_FLOW_TRAIL-iTrail)*(1.0f/CT_WATER_FLOW_TRAIL); + + FLOAT3D vPos = vCenter + + vX*(afStarsPositions[iStar][0]*fStretchAll*fPowerFactor+fHeight*fT) + + vY*(fT*fT*-5.0f+(afStarsPositions[iStar][1]*fPowerFactor*0.1)) + + vZ*(afStarsPositions[iStar][2]*fPowerFactor*fT*fStretchAll); + + COLOR colWater = pTD->GetTexel( FloatToInt(fT*2048), 0); + ULONG ulA = FloatToInt( ((colWater&CT_AMASK)>>CT_ASHIFT) * fFade); + colWater = (colWater&~CT_AMASK) | (ulA<GetLerpedCurrentTick(); + + SetupParticleTexture( PT_LAVAFLOW); + CTextureData *pTD = (CTextureData *) _toLavaFlowGradient.GetData(); + const FLOATmatrix3D &m = pen->GetRotationMatrix(); + FLOAT3D vX( m(1,1), m(2,1), m(3,1)); + FLOAT3D vY( m(1,2), m(2,2), m(3,2)); + FLOAT3D vZ( m(1,3), m(2,3), m(3,3)); + FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector; + + FLOAT fPowerFactor = Clamp((fNow - fStartTime)/2.0f,0.0f,1.0f); + fPowerFactor *= Clamp(1+(fStopTime-fNow)/2.0f,0.0f,1.0f); + ctParticles = FLOAT(ctParticles) * fPowerFactor; + fHeight *= fPowerFactor; + for( INDEX iStar=0; iStarfStopTime+2.0f) ) continue; + FLOAT fFade; + if (fT>(1.0f-LAVA_FLOW_FADE_OUT)) fFade=(1-fT)*(1/LAVA_FLOW_FADE_OUT); + else fFade=1.0f; + fFade *= (CT_LAVA_FLOW_TRAIL-iTrail)*(1.0f/CT_LAVA_FLOW_TRAIL); + + FLOAT3D vPos = vCenter + + vX*(afStarsPositions[iStar][0]*fStretchAll*fPowerFactor+fHeight*fT) + + vY*(fT*fT*-4.0f+(afStarsPositions[iStar][1]*fPowerFactor*0.1)) + + vZ*(afStarsPositions[iStar][2]*fPowerFactor*fT*fStretchAll); + + COLOR colLava = pTD->GetTexel( FloatToInt(fT*2048), 0); + ULONG ulA = FloatToInt( ((colLava&CT_AMASK)>>CT_ASHIFT) * fFade); + colLava = (colLava&~CT_AMASK) | (ulA<GetLerpedPlacement().pl_PositionVector; + FLOAT fFadeStart = BULLET_SPRAY_FADEOUT_START; + FLOAT fLifeTotal = BULLET_SPRAY_TOTAL_TIME; + FLOAT fFadeLen = fLifeTotal-fFadeStart; + COLOR colStones = C_WHITE; + + FLOAT fMipFactor = Particle_GetMipFactor(); + FLOAT fDisappear = 1.0f; + if( fMipFactor>8.0f) return; + if( fMipFactor>6.0f) + { + fDisappear = 1.0f-(fMipFactor-6.0f)/2.0f; + } + + FLOAT fNow = _pTimer->GetLerpedCurrentTick(); + FLOAT fT=(fNow-tmSpawn); + if( fT>fLifeTotal) return; + INDEX iRnd = INDEX( (tmSpawn*1000.0f)+pen->en_ulID) &63; + FLOAT fSizeStart; + FLOAT fSpeedStart; + FLOAT fConeMultiplier = 1.0f; + COLOR colSmoke; + + switch( eptType) + { + case EPT_BULLET_WATER: + { + Particle_PrepareTexture(&_toBulletWater, PBT_BLEND); + fSizeStart = 0.08f; + fSpeedStart = 1.75f; + fConeMultiplier = 0.125f; + + //FLOAT fFadeStart = BULLET_SPRAY_WATER_FADEOUT_START; + //FLOAT fLifeTotal = BULLET_SPRAY_WATER_TOTAL_TIME; + //FLOAT fFadeLen = fLifeTotal-fFadeStart; + + break; + } + case EPT_BULLET_SAND: + { + colSmoke = 0xFFE8C000; + Particle_PrepareTexture(&_toBulletSand, PBT_BLEND); + fSizeStart = 0.15f; + fSpeedStart = 0.75f; + break; + } + case EPT_BULLET_RED_SAND: + { + colSmoke = 0xA0402000; + colStones = 0x80503000; + Particle_PrepareTexture(&_toBulletSand, PBT_BLEND); + fSizeStart = 0.15f; + fSpeedStart = 0.75f; + break; + } + default: + { + colSmoke = C_WHITE; + Particle_PrepareTexture(&_toBulletStone, PBT_BLEND); + fSizeStart = 0.05f; + fSpeedStart = 1.5f; + } + } + + FLOAT fGA = 10.0f; + + // render particles + for( INDEX iSpray=0; iSpray<12*fDisappear; iSpray++) + { + Particle_SetTexturePart( 512, 512, iSpray&3, 0); + + FLOAT3D vRandomAngle = FLOAT3D( + afStarsPositions[ iSpray+iRnd][0]*3.0f* fConeMultiplier, + (afStarsPositions[ iSpray+iRnd][1]+1.0f)*3.0f, + afStarsPositions[ iSpray+iRnd][2]*3.0f* fConeMultiplier); + FLOAT fSpeedRnd = fSpeedStart+afStarsPositions[ iSpray+iRnd*2][2]; + FLOAT3D vPos = vEntity + (vDirection+vRandomAngle)*(fT*fSpeedRnd)+vGDir*(fT*fT*fGA); + + if( (eptType == EPT_BULLET_WATER) && (vPos(2) < vEntity(2)) ) + { + continue; + } + + FLOAT fSize = fSizeStart + afStarsPositions[ iSpray*2+iRnd*3][0]/20.0f; + FLOAT fRotation = fT*500.0f; + FLOAT fColorFactor = 1.0f; + if( fT>=fFadeStart) + { + fColorFactor = 1-fFadeLen*(fT-fFadeStart); + } + UBYTE ubColor = UBYTE(CT_OPAQUE*fColorFactor); + COLOR col = colStones|ubColor; + Particle_RenderSquare( vPos, fSize, fRotation, col); + } + Particle_Flush(); + + //--------------------------------------- + if( (fT=BULLET_SPARK_FADEOUT_START) + { + fColorFactor = 1-BULLET_SPARK_FADEOUT_LEN*(fT-BULLET_SPARK_FADEOUT_START); + } + UBYTE ubColor = UBYTE(CT_OPAQUE*fColorFactor); + COLOR col = RGBToColor(ubColor,ubColor,ubColor)|CT_OPAQUE; + Particle_RenderLine( vPos0, vPos1, 0.05f, col); + } + Particle_Flush(); + } + + //--------------------------------------- + if( (fT0.5) { + // use cross product of +x axis and plane normal as +s axis + vX = FLOAT3D(1.0f, 0.0f, 0.0f)*vY; + // if the plane is mostly vertical + } else { + // use cross product of +y axis and plane normal as +s axis + vX = FLOAT3D(0.0f, 1.0f, 0.0f)*vY; + } + // make +s axis normalized + vX.Normalize(); + + // use cross product of plane normal and +s axis as +t axis + vZ = vX*vY; + vZ.Normalize(); +} + +void Particles_EmptyShells( CEntity *pen, ShellLaunchData *asldData) +{ + FLOAT tmNow = _pTimer->GetLerpedCurrentTick(); + FLOAT fGA = ((CMovableEntity *)pen)->en_fGravityA; + FLOAT3D vGDir = ((CMovableEntity *)pen)->en_vGravityDir; + INDEX iRow, iColumn; + + for( INDEX iShell=0; iShell (tmLaunch+fLife) ) continue; + FLOAT fTRatio = fT/fLife; + INDEX iFrame = INDEX( fTRatio*16*8)%16; + iRow = iFrame/4; + iColumn = iFrame%4; + Particle_SetTexturePart( 256, 256, iColumn, iRow); + FLOAT3D vPos = (sld.sld_vPos)+(sld.sld_vSpeed*fT)+(vGDir*(fT*fT*fGA/2.0f)); + Particle_RenderSquare( vPos, 0.05f, 0, C_WHITE|CT_OPAQUE); + break; + } + case ESL_SHOTGUN: + { + FLOAT fLife = 1.5f; + if( tmNow > (tmLaunch+fLife) ) continue; + FLOAT fTRatio = fT/fLife; + INDEX iFrame = INDEX( fTRatio*16*8)%16; + iRow = 4+iFrame/4; + iColumn = iFrame%4; + Particle_SetTexturePart( 256, 256, iColumn, iRow); + FLOAT3D vPos = (sld.sld_vPos)+(sld.sld_vSpeed*fT)+(vGDir*(fT*fT*fGA/2.0f)); + Particle_RenderSquare( vPos, 0.05f, 0, C_WHITE|CT_OPAQUE); + break; + } + case ESL_BUBBLE: + { + INDEX iRnd = (INDEX(tmLaunch*1234))%CT_MAX_PARTICLES_TABLE; + FLOAT fLife = 4.0f; + if( tmNow > (tmLaunch+fLife) ) continue; + Particle_SetTexturePart( 512, 512, 2, 0); + + FLOAT3D vX, vZ; + MakeBaseFromVector( sld.sld_vUp, vX, vZ); + + FLOAT fZF = sin( afStarsPositions[iRnd+2][0]*PI); + FLOAT fXF = cos( afStarsPositions[iRnd+2][0]*PI); + + FLOAT fAmpl = ClampUp( fT+afStarsPositions[iRnd+1][1]+0.5f, 2.0f)/64; + FLOAT fFormulae = fAmpl * sin(afStarsPositions[iRnd][1]+fT*afStarsPositions[iRnd][2]*2); + + FLOAT fColorFactor = 1.0f; + if( fT>fLife/2) + { + fColorFactor = -fT+fLife; + } + UBYTE ubAlpha = CT_OPAQUE; + FLOAT3D vSpeedPower = sld.sld_vSpeed/(1.0f+fT*fT); + + FLOAT3D vPos = sld.sld_vPos + + vX*fFormulae*fXF+ + vZ*fFormulae*fZF+ + sld.sld_vUp*fT/4.0f*(0.8f+afStarsPositions[iRnd][1]/8.0f)+ + vSpeedPower*fT; + FLOAT fSize = 0.02f + afStarsPositions[iRnd+3][1]*0.01f; + Particle_RenderSquare( vPos, fSize, 0, C_WHITE|ubAlpha); + break; + } + case ESL_SHOTGUN_SMOKE: + { + FLOAT fLife = 1.0f; + if( fT0.0f) + { + // render smoke + INDEX iRnd = (INDEX(tmLaunch*1234))%CT_MAX_PARTICLES_TABLE; + //FLOAT fTRatio = fT/fLife; + INDEX iColumn = 4+INDEX( iShell)%4; + Particle_SetTexturePart( 256, 256, iColumn, 2); + + FLOAT3D vPos = sld.sld_vPos + sld.sld_vUp*(afStarsPositions[iRnd][0]/2.0f+0.5f)*fT + sld.sld_vSpeed*fT/(1+fT*fT); + FLOAT fColorFactor = (fLife-fT)/fLife/(afStarsPositions[iRnd+1][0]*2+4.0f); + FLOAT fRotation = afStarsPositions[iShell][1]*200*fT; + FLOAT fSize = (0.0125f+fT/(5.0f+afStarsPositions[iRnd+1][0]*2.0f))*sld.sld_fSize; + UBYTE ubAlpha = UBYTE(CT_OPAQUE*ClampUp(fColorFactor*sld.sld_fSize, 1.0f)); + COLOR colSmoke = C_WHITE; + Particle_RenderSquare( vPos, fSize, fRotation, colSmoke|ubAlpha); + } + break; + } + case ESL_COLT_SMOKE: + { + FLOAT fLife = 1.0f; + if( fT0.0f) + { + CPlayer &plr = (CPlayer&)*pen; + CPlacement3D plPipe; + plr.GetLerpedWeaponPosition(sld.sld_vPos, plPipe); + FLOATmatrix3D m; + MakeRotationMatrixFast(m, plPipe.pl_OrientationAngle); + FLOAT3D vUp( m(1,2), m(2,2), m(3,2)); + + INDEX iRnd = (INDEX(tmLaunch*1234))%CT_MAX_PARTICLES_TABLE; + //FLOAT fTRatio = fT/fLife; + INDEX iColumn = 4+INDEX( iShell)%4; + Particle_SetTexturePart( 256, 256, iColumn, 2); + + FLOAT3D vPos = plPipe.pl_PositionVector+vUp*(afStarsPositions[iRnd][0]/4.0f+0.3f)*fT; + FLOAT fColorFactor = (fLife-fT)/fLife/(afStarsPositions[iRnd+1][0]*2+4.0f); + FLOAT fRotation = afStarsPositions[iShell][1]*500*fT; + FLOAT fSize = 0.0025f+fT/(10.0f+(afStarsPositions[iRnd+1][0]+0.5f)*10.0f); + UBYTE ubAlpha = UBYTE(CT_OPAQUE*fColorFactor); + COLOR colSmoke = C_WHITE; + Particle_RenderSquare( vPos, fSize, fRotation, colSmoke|ubAlpha); + } + break; + } + } + } + Particle_Flush(); +} + +#define FADE_IN_LENGHT 1.0f +#define FADE_OUT_LENGHT 1.5f +#define FADE_IN_START 0.0f +#define SPIRIT_SPIRAL_START 1.0f +#define FADE_OUT_START 1.75f + +#define FADE_IN_END (FADE_IN_START+FADE_IN_LENGHT) +#define FADE_OUT_END (FADE_OUT_START+FADE_OUT_LENGHT) + +void Particles_Death(CEntity *pen, TIME tmStart) +{ + FLOAT fMipFactor = Particle_GetMipFactor(); + BOOL bVisible = pen->en_pmoModelObject->IsModelVisible( fMipFactor); + if( !bVisible) return; + + FLOAT fTime = _pTimer->GetLerpedCurrentTick()-tmStart; + // don't render particles before fade in and after fadeout + if( (fTimeFADE_OUT_END)) { + return; + } + FLOAT fPowerTime = pow(fTime-SPIRIT_SPIRAL_START, 2.5f); + + // fill array with absolute vertices of entity's model and its attached models + pen->GetModelVerticesAbsolute(avVertices, 0.05f, fMipFactor); + + // get entity position and orientation + const FLOATmatrix3D &m = pen->GetRotationMatrix(); + FLOAT3D vX( m(1,1), m(2,1), m(3,1)); + FLOAT3D vY( m(1,2), m(2,2), m(3,2)); + FLOAT3D vZ( m(1,3), m(2,3), m(3,3)); + FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector; + + SetupParticleTexture( PT_STAR07); + + // calculate color factor (for fade in/out) + FLOAT fColorFactor = 1.0f; + if( (fTime>=FADE_IN_START) && (fTime<=FADE_IN_END)) + { + fColorFactor = 1/FADE_IN_LENGHT*(fTime-FADE_IN_START); + } + else if( (fTime>=FADE_OUT_START) && (fTime<=FADE_OUT_END)) + { + fColorFactor = -1/FADE_OUT_LENGHT*(fTime-FADE_OUT_END); + } + + UBYTE ubColor = UBYTE(CT_OPAQUE*fColorFactor); + COLOR col = RGBToColor(ubColor,ubColor,ubColor)|CT_OPAQUE; + + INDEX ctVtx = avVertices.Count(); + FLOAT fSpeedFactor = 1.0f/ctVtx; + + // get corp size + FLOATaabbox3D box; + pen->en_pmoModelObject->GetCurrentFrameBBox(box); + FLOAT fHeightStretch = box.Size()(2); + + FLOAT fStep = ClampDn( fMipFactor, 1.0f); + for( FLOAT fVtx=0.0f; fVtxen_pmoModelObject->IsModelVisible( fMipFactor); + if( !bVisible) return; + + FLOAT fTime = _pTimer->GetLerpedCurrentTick()-tmStart; + // don't render particles before fade in and after fadeout + if( (fTimeAPPEAR_OUT_END)) { + return; + } + //FLOAT fPowerTime = pow(fTime-SPIRIT_SPIRAL_START, 2.5f); + + // fill array with absolute vertices of entity's model and its attached models + pen->GetModelVerticesAbsolute(avVertices, 0.05f, fMipFactor); + + // get entity position and orientation + const FLOATmatrix3D &m = pen->GetRotationMatrix(); + FLOAT3D vX( m(1,1), m(2,1), m(3,1)); + FLOAT3D vY( m(1,2), m(2,2), m(3,2)); + FLOAT3D vZ( m(1,3), m(2,3), m(3,3)); + //FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector; + + SetupParticleTexture( PT_STAR07); + + // calculate color factor (for fade in/out) + FLOAT fColorFactor = 1.0f; + if( (fTime>=APPEAR_IN_START) && (fTime<=APPEAR_IN_END)) + { + fColorFactor = 1/APPEAR_IN_LENGHT*(fTime-APPEAR_IN_START); + } + else if( (fTime>=APPEAR_OUT_START) && (fTime<=APPEAR_OUT_END)) + { + fColorFactor = -1/APPEAR_OUT_LENGHT*(fTime-APPEAR_OUT_END); + } + + UBYTE ubColor = UBYTE(CT_OPAQUE*fColorFactor); + COLOR col = RGBToColor(ubColor,ubColor,ubColor)|CT_OPAQUE; + + INDEX ctVtx = avVertices.Count(); + //FLOAT fSpeedFactor = 1.0f/ctVtx; + + // get corp size + FLOATaabbox3D box; + pen->en_pmoModelObject->GetCurrentFrameBBox(box); + //FLOAT fHeightStretch = box.Size()(2); + + FLOAT fStep = ClampDn( fMipFactor, 1.0f); + for( FLOAT fVtx=0.0f; fVtxGetLerpedPlacement().pl_PositionVector; + FLOAT fBoxSize = boxOwner.Size().Length()*0.1f; + FLOAT fEnemySizeModifier = (fBoxSize-0.2)/1.0f+1.0f; + FLOAT fRotation = 0.0f; + + // readout blood type + const INDEX iBloodType = GetSP()->sp_iBlood; + + // determine time difference + FLOAT fNow = _pTimer->GetLerpedCurrentTick(); + + // prepare texture + switch(sptType) { + case SPT_BLOOD: + case SPT_SLIME: + { + if( iBloodType<1) return; + if( iBloodType==3) Particle_PrepareTexture( &_toFlowerSprayTexture, PBT_BLEND); + else Particle_PrepareTexture( &_toBloodSprayTexture, PBT_BLEND); + break; + } + case SPT_BONES: + { + Particle_PrepareTexture( &_toBonesSprayTexture, PBT_BLEND); + break; + } + case SPT_FEATHER: + { + Particle_PrepareTexture( &_toFeatherSprayTexture, PBT_BLEND); + fDamagePower*=2.0f; + break; + } + case SPT_STONES: + { + Particle_PrepareTexture( &_toStonesSprayTexture, PBT_BLEND); + fDamagePower*=3.0f; + break; + } + case SPT_WOOD: + { + Particle_PrepareTexture( &_toWoodSprayTexture, PBT_BLEND); + fDamagePower*=5.0f; + break; + } + case SPT_SMALL_LAVA_STONES: + { + Particle_PrepareTexture( &_toLavaSprayTexture, PBT_BLEND); + fDamagePower *= 0.75f; + break; + } + case SPT_LAVA_STONES: + { + Particle_PrepareTexture( &_toLavaSprayTexture, PBT_BLEND); + fDamagePower *=3.0f; + break; + } + case SPT_BEAST_PROJECTILE_SPRAY: + { + Particle_PrepareTexture( &_toBeastProjectileSprayTexture, PBT_BLEND); + fDamagePower*=3.0f; + break; + } + case SPT_ELECTRICITY_SPARKS: + { + Particle_PrepareTexture( &_toMetalSprayTexture, PBT_BLEND); + break; + } + default: ASSERT(FALSE); + return; + } + + FLOAT fT=(fNow-tmStarted); + for( INDEX iSpray=0; iSprayBLOOD_SPRAY_FADE_OUT_START) + { + fSize=(-1/(BLOOD_SPRAY_TOTAL_TIME-BLOOD_SPRAY_FADE_OUT_START))*(fT-BLOOD_SPRAY_TOTAL_TIME); + fFade = fSize; + } + else if( fT>BLOOD_SPRAY_TOTAL_TIME) + { + fSize=0.0f; + fFade =0.0f; + } + else + { + fSize=1.0f; + fFade = fSize; + } + FLOAT fMipFactor = Particle_GetMipFactor(); + FLOAT fMipSizeAffector = Clamp( fMipFactor/4.0f, 0.05f, 1.0f); + fSize *= fMipSizeAffector*fDamagePower*fEnemySizeModifier; + + FLOAT3D vRandomAngle = FLOAT3D( + afStarsPositions[ iSpray][0]*1.75f, + (afStarsPositions[ iSpray][1]+1.0f)*1.0f, + afStarsPositions[ iSpray][2]*1.75f); + FLOAT fSpeedModifier = afStarsPositions[ iSpray+BLOOD_SPRAYS][0]*0.5f; + + FLOAT fSpeed = BLOOD_SPRAY_SPEED_MIN+(BLOOD_SPRAY_TOTAL_TIME-fT)/BLOOD_SPRAY_TOTAL_TIME; + FLOAT3D vPos = vWoundPos + (vSpilDirection+vRandomAngle)*(fT*(fSpeed+fSpeedModifier))+vGDir*(fT*fT*fGA/4.0f); + + UBYTE ubAlpha = UBYTE(CT_OPAQUE*fFade); + FLOAT fSizeModifier = afStarsPositions[ int(iSpray+tmStarted*50)%CT_MAX_PARTICLES_TABLE][1]*0.5+1.0f; + + COLOR col = C_WHITE|CT_OPAQUE; + // prepare texture + switch(sptType) { + case SPT_BLOOD: + { + UBYTE ubRndCol = UBYTE( 128+afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][0]*64); + if( iBloodType==2) col = RGBAToColor( ubRndCol, 0, 0, ubAlpha); + if( iBloodType==1) col = RGBAToColor( 0, ubRndCol, 0, ubAlpha); + break; + } + case SPT_SLIME: + { + UBYTE ubRndCol = UBYTE( 128+afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][0]*64); + if( iBloodType!=3) col = RGBAToColor(0, ubRndCol, 0, ubAlpha); + break; + } + case SPT_BONES: + { + UBYTE ubRndH = UBYTE( 8+afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][0]*16); + UBYTE ubRndS = UBYTE( 96+(afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][1]+0.5)*64); + UBYTE ubRndV = UBYTE( 64+(afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][2])*64); + col = HSVToColor(ubRndH, ubRndS, ubRndV)|ubAlpha; + fSize/=1.5f; + break; + } + case SPT_FEATHER: + { + if(iSpray>=BLOOD_SPRAYS/2) + { + UBYTE ubRndCol = UBYTE( 128+afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][0]*64); + if( iBloodType==2) col = RGBAToColor( ubRndCol, 0, 0, ubAlpha); + if( iBloodType==1) col = RGBAToColor( 0, ubRndCol, 0, ubAlpha); + } + else + { + UBYTE ubRndH = UBYTE( 32+afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][0]*16); + //UBYTE ubRndS = UBYTE( 127+(afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][1]+0.5)*128); + UBYTE ubRndV = UBYTE( 159+(afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][2])*192); + col = HSVToColor(ubRndH, 0, ubRndV)|ubAlpha; + fSize/=2.0f; + fRotation = fT*200.0f; + } + break; + } + case SPT_STONES: + { + UBYTE ubRndH = UBYTE( 24+afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][0]*16); + UBYTE ubRndS = UBYTE( 32+(afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][1]+0.5)*64); + UBYTE ubRndV = UBYTE( 196+(afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][2])*128); + col = HSVToColor(ubRndH, ubRndS, ubRndV)|ubAlpha; + fSize*=0.10f; + fRotation = fT*200.0f; + break; + } + case SPT_WOOD: + { + UBYTE ubRndH = UBYTE( 16+afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][0]*16); + UBYTE ubRndS = UBYTE( 96+(afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][1]+0.5)*32); + UBYTE ubRndV = UBYTE( 96+(afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][2])*96); + col = HSVToColor(ubRndH, ubRndS, ubRndV)|ubAlpha; + fSize*=0.15f; + fRotation = fT*300.0f; + break; + } + case SPT_LAVA_STONES: + case SPT_SMALL_LAVA_STONES: + { + col = C_WHITE|ubAlpha; + fSize/=12.0f; + fRotation = fT*200.0f; + break; + } + case SPT_BEAST_PROJECTILE_SPRAY: + { + col = C_WHITE|ubAlpha; + fSize/=12.0f; + fRotation = fT*200.0f; + break; + } + case SPT_ELECTRICITY_SPARKS: + { + UBYTE ubRndH = UBYTE( 180+afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][0]*16); + UBYTE ubRndS = 0; + UBYTE ubRndV = 255; + col = HSVToColor(ubRndH, ubRndS, ubRndV)|ubAlpha; + fSize/=32.0f; + fRotation = fT*200.0f; + break; + } + } + Particle_RenderSquare( vPos, 0.25f*fSize*fSizeModifier, fRotation, col); + } + + // all done + Particle_Flush(); +} + +// spray some stones along obelisk +void Particles_DestroyingObelisk(CEntity *penSpray, FLOAT tmStarted) +{ + FLOAT fNow = _pTimer->GetLerpedCurrentTick(); + FLOAT fT=(fNow-tmStarted); + Particle_PrepareTexture( &_toStonesSprayTexture, PBT_BLEND); + + FLOAT fTotalTime = 10.0f; + FLOAT fFadeOutStart = 7.5f; + FLOAT fFadeInEnd = 1.0f; + FLOAT3D vG = FLOAT3D(0.0f,-20.0f,0.0f); + + for( INDEX iStone=0; iStone<128; iStone++) + { + INDEX idx = int(iStone+tmStarted*33)%CT_MAX_PARTICLES_TABLE; + FLOAT3D vSpeed = FLOAT3D( + afStarsPositions[ idx][0], + afStarsPositions[ idx][1], + afStarsPositions[ idx][2]); + vSpeed(2) += 0.25f; + vSpeed *= 50.0f; + + // calculate position + FLOAT3D vPos = penSpray->GetPlacement().pl_PositionVector + + vSpeed*fT + + vG*fT*fT; + vPos(2) += (afStarsPositions[ int(iStone+tmStarted*100)%CT_MAX_PARTICLES_TABLE][1]+0.5)*116.0f; + + FLOAT fFade; + // apply fade + if( fTfFadeOutStart) + { + fFade = (-1/(fTotalTime-fFadeOutStart))*(fT-fTotalTime); + } + else if( fT>fTotalTime) + { + fFade =0.0f; + } + else + { + fFade = 1.0f; + } + + UBYTE ubRndH = UBYTE( 16+afStarsPositions[ int(iStone+tmStarted*10)%CT_MAX_PARTICLES_TABLE][0]*8); + UBYTE ubRndS = UBYTE( 96+(afStarsPositions[ int(iStone+tmStarted*10)%CT_MAX_PARTICLES_TABLE][1]+0.5)*64); + UBYTE ubRndV = UBYTE( 128+(afStarsPositions[ int(iStone+tmStarted*10)%CT_MAX_PARTICLES_TABLE][2])*64); + UBYTE ubAlpha = UBYTE(CT_OPAQUE*fFade); + COLOR col = HSVToColor(ubRndH, ubRndS, ubRndV)|ubAlpha; + + FLOAT fSize=(afStarsPositions[ int(iStone+tmStarted*100)%CT_MAX_PARTICLES_TABLE][2]+1.0f)*1.5f; + FLOAT fRotation = fT*200.0f; + + Particle_SetTexturePart( 256, 256, ((int(tmStarted*100.0f))%8+iStone)%8, 0); + Particle_RenderSquare( vPos, fSize, fRotation, col); + } + // all done + Particle_Flush(); +} + +// spray some stones along pylon +void Particles_DestroyingPylon(CEntity *penSpray, FLOAT3D vDamageDir, FLOAT tmStarted) +{ + FLOAT fNow = _pTimer->GetLerpedCurrentTick(); + FLOAT fT=(fNow-tmStarted); + Particle_PrepareTexture( &_toStonesSprayTexture, PBT_BLEND); + + FLOAT fTotalTime = 10.0f; + FLOAT fFadeOutStart = 7.5f; + FLOAT fFadeInEnd = 1.0f; + FLOAT3D vG = FLOAT3D(0.0f,-20.0f,0.0f); + const FLOATmatrix3D &m = penSpray->GetRotationMatrix(); + + for( INDEX iStone=0; iStone<128; iStone++) + { + INDEX idx = int(iStone+tmStarted*33)%CT_MAX_PARTICLES_TABLE; + FLOAT3D vSpeed = vDamageDir+FLOAT3D( + afStarsPositions[ idx][0], + afStarsPositions[ idx][1], + afStarsPositions[ idx][2]); + vSpeed *= 50.0f; + + // calculate position + FLOAT3D vPos = penSpray->GetPlacement().pl_PositionVector + + vSpeed*fT*m + + vG*fT*fT; + FLOAT3D vOffset = FLOAT3D(0.0f,0.0f,0.0f); + vOffset(1) = (afStarsPositions[ int(iStone+tmStarted*100)%CT_MAX_PARTICLES_TABLE][1])*32.0f; + vOffset(2) = (afStarsPositions[ int(iStone+tmStarted*100)%CT_MAX_PARTICLES_TABLE][2]+0.5)*56.0f; + vPos += vOffset*m; + + FLOAT fFade; + // apply fade + if( fTfFadeOutStart) + { + fFade = (-1/(fTotalTime-fFadeOutStart))*(fT-fTotalTime); + } + else if( fT>fTotalTime) + { + fFade =0.0f; + } + else + { + fFade = 1.0f; + } + + UBYTE ubRndH = UBYTE( 16+afStarsPositions[ int(iStone+tmStarted*10)%CT_MAX_PARTICLES_TABLE][0]*8); + UBYTE ubRndS = UBYTE( 96+(afStarsPositions[ int(iStone+tmStarted*10)%CT_MAX_PARTICLES_TABLE][1]+0.5)*64); + UBYTE ubRndV = UBYTE( 128+(afStarsPositions[ int(iStone+tmStarted*10)%CT_MAX_PARTICLES_TABLE][2])*64); + UBYTE ubAlpha = UBYTE(CT_OPAQUE*fFade); + COLOR col = HSVToColor(ubRndH, ubRndS, ubRndV)|ubAlpha; + + FLOAT fSize=(afStarsPositions[ int(iStone+tmStarted*100)%CT_MAX_PARTICLES_TABLE][2]+1.0f)*1.5f; + FLOAT fRotation = fT*200.0f; + + Particle_SetTexturePart( 256, 256, ((int(tmStarted*100.0f))%8+iStone)%8, 0); + Particle_RenderSquare( vPos, fSize, fRotation, col); + } + // all done + Particle_Flush(); +} + +// spray some stones in the air +void Particles_HitGround(CEntity *penSpray, FLOAT tmStarted, FLOAT fSizeMultiplier) +{ + FLOAT fNow = _pTimer->GetLerpedCurrentTick(); + FLOAT fT=(fNow-tmStarted); + Particle_PrepareTexture( &_toStonesSprayTexture, PBT_BLEND); + + FLOAT fTotalTime = 10.0f; + FLOAT fFadeOutStart = 7.5f; + FLOAT fFadeInEnd = 1.0f; + FLOAT3D vG = FLOAT3D(0.0f,-30.0f,0.0f); + + for( INDEX iStone=0; iStone<64; iStone++) + { + INDEX idx = int(iStone+tmStarted*33)%CT_MAX_PARTICLES_TABLE; + FLOAT3D vSpeed = FLOAT3D( + afStarsPositions[ idx][0]*1.5f, + (afStarsPositions[ idx][1]+0.5f)*3, + afStarsPositions[ idx][2]*1.5f); + FLOAT fSpeedMultiplier = (fSizeMultiplier-1)*(0.5f-1.0f)/(0.025f-1.0f)+1.0f; + vSpeed *= 50.0f*fSpeedMultiplier; + + // calculate position + FLOAT3D vPos = penSpray->GetPlacement().pl_PositionVector + + vSpeed*fT + + vG*fT*fT; + + FLOAT fFade; + // apply fade + if( fTfFadeOutStart) + { + fFade = (-1/(fTotalTime-fFadeOutStart))*(fT-fTotalTime); + } + else if( fT>fTotalTime) + { + fFade =0.0f; + } + else + { + fFade = 1.0f; + } + + UBYTE ubRndH = UBYTE( 16+afStarsPositions[ int(iStone+tmStarted*10)%CT_MAX_PARTICLES_TABLE][0]*8); + UBYTE ubRndS = UBYTE( 96+(afStarsPositions[ int(iStone+tmStarted*10)%CT_MAX_PARTICLES_TABLE][1]+0.5)*64); + UBYTE ubRndV = UBYTE( 128+(afStarsPositions[ int(iStone+tmStarted*10)%CT_MAX_PARTICLES_TABLE][2])*64); + UBYTE ubAlpha = UBYTE(CT_OPAQUE*fFade); + COLOR col = HSVToColor(ubRndH, ubRndS, ubRndV)|ubAlpha; + + FLOAT fSize=(afStarsPositions[ int(iStone+tmStarted*100)%CT_MAX_PARTICLES_TABLE][2]+1.0f)*4.0f*fSizeMultiplier; + FLOAT fRotation = fT*200.0f; + + Particle_SetTexturePart( 256, 256, ((int(tmStarted*100.0f))%8+iStone)%8, 0); + Particle_RenderSquare( vPos, fSize, fRotation, col); + } + // all done + Particle_Flush(); +} diff --git a/Sources/Entities/Common/PathFinding.cpp b/Sources/Entities/Common/PathFinding.cpp index 91742a6..50966e8 100644 --- a/Sources/Entities/Common/PathFinding.cpp +++ b/Sources/Entities/Common/PathFinding.cpp @@ -1,282 +1,275 @@ -#include "../StdH/StdH.h" -#include "Entities/Common/PathFinding.h" -#include "Entities/NavigationMarker.h" - -#define PRINTOUT(_dummy) -//#define PRINTOUT(something) something - -// open and closed lists of nodes -static CListHead _lhOpen; -static CListHead _lhClosed; - -FLOAT NodeDistance(CPathNode *ppn0, CPathNode *ppn1) -{ - return ( - ppn0->pn_pnmMarker->GetPlacement().pl_PositionVector - - ppn1->pn_pnmMarker->GetPlacement().pl_PositionVector).Length(); -} - -CPathNode::CPathNode(class CNavigationMarker *penMarker) -{ - pn_pnmMarker = penMarker; - pn_ppnParent = NULL; - pn_fG = 0.0f; - pn_fH = 0.0f; - pn_fF = 0.0f; -} - -CPathNode::~CPathNode(void) -{ - // detach from marker when deleting - ASSERT(pn_pnmMarker!=NULL); - pn_pnmMarker->m_ppnNode = NULL; -} - -// get name of this node -const CTString &CPathNode::GetName(void) -{ +#include "../StdH/StdH.h" +#include "Entities/Common/PathFinding.h" +#include "Entities/NavigationMarker.h" + +#define PRINTOUT(_dummy) +//#define PRINTOUT(something) something + +// open and closed lists of nodes +static CListHead _lhOpen; +static CListHead _lhClosed; + +FLOAT NodeDistance(CPathNode *ppn0, CPathNode *ppn1) +{ + return ( + ppn0->pn_pnmMarker->GetPlacement().pl_PositionVector - + ppn1->pn_pnmMarker->GetPlacement().pl_PositionVector).Length(); +} + +CPathNode::CPathNode(class CNavigationMarker *penMarker): pn_pnmMarker(penMarker), pn_ppnParent(NULL), pn_fG(0.0f), pn_fH(0.0f), pn_fF(0.0f){} + +CPathNode::~CPathNode(void) +{ + // detach from marker when deleting + ASSERT(pn_pnmMarker!=NULL); + pn_pnmMarker->m_ppnNode = NULL; +} + +// get name of this node +const CTString &CPathNode::GetName(void) +{ ASSERT(this!=NULL); - static CTString strNone=""; - if (pn_pnmMarker==NULL) { - return strNone; - } else { - return pn_pnmMarker->GetName(); - } -} - -// get link with given index or null if no more (for iteration along the graph) -CPathNode *CPathNode::GetLink(INDEX i) -{ - ASSERT(this!=NULL); - if (pn_pnmMarker==NULL) { - ASSERT(FALSE); - return NULL; - } - CNavigationMarker *pnm = pn_pnmMarker->GetLink(i); - if (pnm==NULL) { - return NULL; - } - return pnm->GetPathNode(); -} - -// add given node to open list, sorting best first -static void SortIntoOpenList(CPathNode *ppnLink) -{ - // start at head of the open list - LISTITER(CPathNode, pn_lnInOpen) itpn(_lhOpen); - // while the given node is further than the one in list - while(ppnLink->pn_fF>itpn->pn_fF && !itpn.IsPastEnd()) { - // move to next node - itpn.MoveToNext(); - } - - // if past the end of list - if (itpn.IsPastEnd()) { - // add to the end of list - _lhOpen.AddTail(ppnLink->pn_lnInOpen); - // if not past end of list - } else { - // add before current node - itpn.InsertBeforeCurrent(ppnLink->pn_lnInOpen); - } -} - -// find shortest path from one marker to another -static BOOL FindPath(CNavigationMarker *pnmSrc, CNavigationMarker *pnmDst) -{ - - ASSERT(pnmSrc!=pnmDst); - CPathNode *ppnSrc = pnmSrc->GetPathNode(); - CPathNode *ppnDst = pnmDst->GetPathNode(); - - PRINTOUT(CPrintF("--------------------\n")); - PRINTOUT(CPrintF("FindPath(%s, %s)\n", ppnSrc->GetName(), ppnDst->GetName())); - - // start with empty open and closed lists - ASSERT(_lhOpen.IsEmpty()); - ASSERT(_lhClosed.IsEmpty()); - - // add the start node to open list - ppnSrc->pn_fG = 0.0f; - ppnSrc->pn_fH = NodeDistance(ppnSrc, ppnDst); - ppnSrc->pn_fF = ppnSrc->pn_fG +ppnSrc->pn_fH; - _lhOpen.AddTail(ppnSrc->pn_lnInOpen); - PRINTOUT(CPrintF("StartState: %s\n", ppnSrc->GetName())); - - // while the open list is not empty - while (!_lhOpen.IsEmpty()) { - // get the first node from open list (that is, the one with lowest F) - CPathNode *ppnNode = LIST_HEAD(_lhOpen, CPathNode, pn_lnInOpen); - ppnNode->pn_lnInOpen.Remove(); - _lhClosed.AddTail(ppnNode->pn_lnInClosed); - PRINTOUT(CPrintF("Node: %s - moved from OPEN to CLOSED\n", ppnNode->GetName())); - - // if this is the goal - if (ppnNode==ppnDst) { - PRINTOUT(CPrintF("PATH FOUND!\n")); - // the path is found - return TRUE; - } - - // for each link of current node - CPathNode *ppnLink = NULL; - for(INDEX i=0; (ppnLink=ppnNode->GetLink(i))!=NULL; i++) { - PRINTOUT(CPrintF(" Link %d: %s\n", i, ppnLink->GetName())); - // get cost to get to this node if coming from current node - FLOAT fNewG = ppnLink->pn_fG+NodeDistance(ppnNode, ppnLink); - // if a shorter path already exists - if ((ppnLink->pn_lnInOpen.IsLinked() || ppnLink->pn_lnInClosed.IsLinked()) && fNewG>=ppnLink->pn_fG) { - PRINTOUT(CPrintF(" shorter path exists through: %s\n", ppnLink->pn_ppnParent->GetName())); - // skip this link - continue; - } - // remember this path - ppnLink->pn_ppnParent = ppnNode; - ppnLink->pn_fG = fNewG; - ppnLink->pn_fH = NodeDistance(ppnLink, ppnDst); - ppnLink->pn_fF = ppnLink->pn_fG + ppnLink->pn_fH; - // remove from closed list, if in it - if (ppnLink->pn_lnInClosed.IsLinked()) { - ppnLink->pn_lnInClosed.Remove(); - PRINTOUT(CPrintF(" %s removed from CLOSED\n", ppnLink->GetName())); - } - // add to open if not in it - if (!ppnLink->pn_lnInOpen.IsLinked()) { - SortIntoOpenList(ppnLink); - PRINTOUT(CPrintF(" %s added to OPEN\n", ppnLink->GetName())); - } - } - } - - // if we get here, there is no path - PRINTOUT(CPrintF("PATH NOT FOUND!\n")); - return FALSE; -} - -// clear all temporary structures used for path finding -static void ClearPath(CEntity *penThis) -{ - {FORDELETELIST(CPathNode, pn_lnInOpen, _lhOpen, itpn) { - delete &itpn.Current(); - }} - {FORDELETELIST(CPathNode, pn_lnInClosed, _lhClosed, itpn) { - delete &itpn.Current(); - }} - -#ifndef NDEBUG - // for each navigation marker in the world - {FOREACHINDYNAMICCONTAINER(penThis->en_pwoWorld->wo_cenEntities, CEntity, iten) { - if (!IsOfClass(iten, "NavigationMarker")) { - continue; - } - CNavigationMarker &nm = (CNavigationMarker&)*iten; - ASSERT(nm.m_ppnNode==NULL); - }} -#endif -} - -// find marker closest to a given position -static void FindClosestMarker( - CEntity *penThis, const FLOAT3D &vSrc, CEntity *&penMarker, FLOAT3D &vPath) -{ - CNavigationMarker *pnmMin = NULL; - FLOAT fMinDist = UpperLimit(0.0f); - // for each sector this entity is in - {FOREACHSRCOFDST(penThis->en_rdSectors, CBrushSector, bsc_rsEntities, pbsc) - // for each navigation marker in that sector - {FOREACHDSTOFSRC(pbsc->bsc_rsEntities, CEntity, en_rdSectors, pen) - if (!IsOfClass(pen, "NavigationMarker")) { - continue; - } - CNavigationMarker &nm = (CNavigationMarker&)*pen; - - // get distance from source - FLOAT fDist = (vSrc-nm.GetPlacement().pl_PositionVector).Length(); - // if closer than best found - if(fDistGetPlacement().pl_PositionVector; - penMarker = pnmMin; -} - -// find first marker for path navigation -void PATH_FindFirstMarker(CEntity *penThis, const FLOAT3D &vSrc, const FLOAT3D &vDst, CEntity *&penMarker, FLOAT3D &vPath) -{ - // find closest markers to source and destination positions - CNavigationMarker *pnmSrc; - FLOAT3D vSrcPath; - FindClosestMarker(penThis, vSrc, (CEntity*&)pnmSrc, vSrcPath); - CNavigationMarker *pnmDst; - FLOAT3D vDstPath; - FindClosestMarker(penThis, vDst, (CEntity*&)pnmDst, vDstPath); - - // if at least one is not found, or if they are same - if (pnmSrc==NULL || pnmDst==NULL || pnmSrc==pnmDst) { - // fail - penMarker = NULL; - vPath = vSrc; - return; - } - - // go to the source marker position - vPath = vSrcPath; - penMarker = pnmSrc; -} - -// find next marker for path navigation -void PATH_FindNextMarker(CEntity *penThis, const FLOAT3D &vSrc, const FLOAT3D &vDst, CEntity *&penMarker, FLOAT3D &vPath) -{ - // find closest marker to destination position - CNavigationMarker *pnmDst; - FLOAT3D vDstPath; - FindClosestMarker(penThis, vDst, (CEntity*&)pnmDst, vDstPath); - - // if at not found, or if same as current - if (pnmDst==NULL || penMarker==pnmDst) { - // fail - penMarker = NULL; - vPath = vSrc; - return; - } - - // try to find shortest path to the destination - BOOL bFound = FindPath((CNavigationMarker*)penMarker, pnmDst); - - // if not found - if (!bFound) { - // just clean up and fail - delete pnmDst->GetPathNode(); - ClearPath(penThis); - penMarker = NULL; - vPath = vSrc; - return; - } - - // find the first marker position after current - CPathNode *ppn = pnmDst->GetPathNode(); - while (ppn->pn_ppnParent!=NULL && ppn->pn_ppnParent->pn_pnmMarker!=penMarker) { - ppn = ppn->pn_ppnParent; - } - penMarker = ppn->pn_pnmMarker; - - // go there - vPath = penMarker->GetPlacement().pl_PositionVector; - - // clean up - ClearPath(penThis); -} \ No newline at end of file + static CTString strNone=""; + if (pn_pnmMarker==NULL) { + return strNone; + } else { + return pn_pnmMarker->GetName(); + } +} + +// get link with given index or null if no more (for iteration along the graph) +CPathNode *CPathNode::GetLink(INDEX i) +{ + ASSERT(this!=NULL); + if (pn_pnmMarker==NULL) { + ASSERT(FALSE); + return NULL; + } + CNavigationMarker *pnm = pn_pnmMarker->GetLink(i); + if (pnm==NULL) { + return NULL; + } + return pnm->GetPathNode(); +} + +// add given node to open list, sorting best first +static void SortIntoOpenList(CPathNode *ppnLink) +{ + // start at head of the open list + LISTITER(CPathNode, pn_lnInOpen) itpn(_lhOpen); + // while the given node is further than the one in list + while(ppnLink->pn_fF>itpn->pn_fF && !itpn.IsPastEnd()) { + // move to next node + itpn.MoveToNext(); + } + + // if past the end of list + if (itpn.IsPastEnd()) { + // add to the end of list + _lhOpen.AddTail(ppnLink->pn_lnInOpen); + // if not past end of list + } else { + // add before current node + itpn.InsertBeforeCurrent(ppnLink->pn_lnInOpen); + } +} + +// find shortest path from one marker to another +static BOOL FindPath(CNavigationMarker *pnmSrc, CNavigationMarker *pnmDst) +{ + + ASSERT(pnmSrc!=pnmDst); + CPathNode *ppnSrc = pnmSrc->GetPathNode(); + CPathNode *ppnDst = pnmDst->GetPathNode(); + + PRINTOUT(CPrintF("--------------------\n")); + PRINTOUT(CPrintF("FindPath(%s, %s)\n", ppnSrc->GetName(), ppnDst->GetName())); + + // start with empty open and closed lists + ASSERT(_lhOpen.IsEmpty()); + ASSERT(_lhClosed.IsEmpty()); + + // add the start node to open list + ppnSrc->pn_fG = 0.0f; + ppnSrc->pn_fH = NodeDistance(ppnSrc, ppnDst); + ppnSrc->pn_fF = ppnSrc->pn_fG +ppnSrc->pn_fH; + _lhOpen.AddTail(ppnSrc->pn_lnInOpen); + PRINTOUT(CPrintF("StartState: %s\n", ppnSrc->GetName())); + + // while the open list is not empty + while (!_lhOpen.IsEmpty()) { + // get the first node from open list (that is, the one with lowest F) + CPathNode *ppnNode = LIST_HEAD(_lhOpen, CPathNode, pn_lnInOpen); + ppnNode->pn_lnInOpen.Remove(); + _lhClosed.AddTail(ppnNode->pn_lnInClosed); + PRINTOUT(CPrintF("Node: %s - moved from OPEN to CLOSED\n", ppnNode->GetName())); + + // if this is the goal + if (ppnNode==ppnDst) { + PRINTOUT(CPrintF("PATH FOUND!\n")); + // the path is found + return TRUE; + } + + // for each link of current node + CPathNode *ppnLink = NULL; + for(INDEX i=0; (ppnLink=ppnNode->GetLink(i))!=NULL; i++) { + PRINTOUT(CPrintF(" Link %d: %s\n", i, ppnLink->GetName())); + // get cost to get to this node if coming from current node + FLOAT fNewG = ppnLink->pn_fG+NodeDistance(ppnNode, ppnLink); + // if a shorter path already exists + if ((ppnLink->pn_lnInOpen.IsLinked() || ppnLink->pn_lnInClosed.IsLinked()) && fNewG>=ppnLink->pn_fG) { + PRINTOUT(CPrintF(" shorter path exists through: %s\n", ppnLink->pn_ppnParent->GetName())); + // skip this link + continue; + } + // remember this path + ppnLink->pn_ppnParent = ppnNode; + ppnLink->pn_fG = fNewG; + ppnLink->pn_fH = NodeDistance(ppnLink, ppnDst); + ppnLink->pn_fF = ppnLink->pn_fG + ppnLink->pn_fH; + // remove from closed list, if in it + if (ppnLink->pn_lnInClosed.IsLinked()) { + ppnLink->pn_lnInClosed.Remove(); + PRINTOUT(CPrintF(" %s removed from CLOSED\n", ppnLink->GetName())); + } + // add to open if not in it + if (!ppnLink->pn_lnInOpen.IsLinked()) { + SortIntoOpenList(ppnLink); + PRINTOUT(CPrintF(" %s added to OPEN\n", ppnLink->GetName())); + } + } + } + + // if we get here, there is no path + PRINTOUT(CPrintF("PATH NOT FOUND!\n")); + return FALSE; +} + +// clear all temporary structures used for path finding +static void ClearPath(CEntity *penThis) +{ + {FORDELETELIST(CPathNode, pn_lnInOpen, _lhOpen, itpn) { + delete &itpn.Current(); + }} + {FORDELETELIST(CPathNode, pn_lnInClosed, _lhClosed, itpn) { + delete &itpn.Current(); + }} + +#ifndef NDEBUG + // for each navigation marker in the world + {FOREACHINDYNAMICCONTAINER(penThis->en_pwoWorld->wo_cenEntities, CEntity, iten) { + if (!IsOfClass(iten, "NavigationMarker")) { + continue; + } + CNavigationMarker &nm = (CNavigationMarker&)*iten; + ASSERT(nm.m_ppnNode==NULL); + }} +#endif +} + +// find marker closest to a given position +static void FindClosestMarker( + CEntity *penThis, const FLOAT3D &vSrc, CEntity *&penMarker, FLOAT3D &vPath) +{ + CNavigationMarker *pnmMin = NULL; + FLOAT fMinDist = UpperLimit(0.0f); + // for each sector this entity is in + {FOREACHSRCOFDST(penThis->en_rdSectors, CBrushSector, bsc_rsEntities, pbsc) + // for each navigation marker in that sector + {FOREACHDSTOFSRC(pbsc->bsc_rsEntities, CEntity, en_rdSectors, pen) + if (!IsOfClass(pen, "NavigationMarker")) { + continue; + } + CNavigationMarker &nm = (CNavigationMarker&)*pen; + + // get distance from source + FLOAT fDist = (vSrc-nm.GetPlacement().pl_PositionVector).Length(); + // if closer than best found + if(fDistGetPlacement().pl_PositionVector; + penMarker = pnmMin; +} + +// find first marker for path navigation +void PATH_FindFirstMarker(CEntity *penThis, const FLOAT3D &vSrc, const FLOAT3D &vDst, CEntity *&penMarker, FLOAT3D &vPath) +{ + // find closest markers to source and destination positions + CNavigationMarker *pnmSrc; + FLOAT3D vSrcPath; + FindClosestMarker(penThis, vSrc, (CEntity*&)pnmSrc, vSrcPath); + CNavigationMarker *pnmDst; + FLOAT3D vDstPath; + FindClosestMarker(penThis, vDst, (CEntity*&)pnmDst, vDstPath); + + // if at least one is not found, or if they are same + if (pnmSrc==NULL || pnmDst==NULL || pnmSrc==pnmDst) { + // fail + penMarker = NULL; + vPath = vSrc; + return; + } + + // go to the source marker position + vPath = vSrcPath; + penMarker = pnmSrc; +} + +// find next marker for path navigation +void PATH_FindNextMarker(CEntity *penThis, const FLOAT3D &vSrc, const FLOAT3D &vDst, CEntity *&penMarker, FLOAT3D &vPath) +{ + // find closest marker to destination position + CNavigationMarker *pnmDst; + FLOAT3D vDstPath; + FindClosestMarker(penThis, vDst, (CEntity*&)pnmDst, vDstPath); + + // if at not found, or if same as current + if (pnmDst==NULL || penMarker==pnmDst) { + // fail + penMarker = NULL; + vPath = vSrc; + return; + } + + // try to find shortest path to the destination + BOOL bFound = FindPath((CNavigationMarker*)penMarker, pnmDst); + + // if not found + if (!bFound) { + // just clean up and fail + delete pnmDst->GetPathNode(); + ClearPath(penThis); + penMarker = NULL; + vPath = vSrc; + return; + } + + // find the first marker position after current + CPathNode *ppn = pnmDst->GetPathNode(); + while (ppn->pn_ppnParent!=NULL && ppn->pn_ppnParent->pn_pnmMarker!=penMarker) { + ppn = ppn->pn_ppnParent; + } + penMarker = ppn->pn_pnmMarker; + + // go there + vPath = penMarker->GetPlacement().pl_PositionVector; + + // clean up + ClearPath(penThis); +} diff --git a/Sources/EntitiesMP/Common/Common.h b/Sources/EntitiesMP/Common/Common.h index f68dee8..304081a 100644 --- a/Sources/EntitiesMP/Common/Common.h +++ b/Sources/EntitiesMP/Common/Common.h @@ -156,14 +156,7 @@ struct DECL_DLL PlayerStats { INDEX ps_iSecrets; TIME ps_tmTime; - PlayerStats(void) - { - ps_iScore = 0; - ps_iKills = 0; - ps_iDeaths = 0; - ps_iSecrets = 0; - ps_tmTime = 0.0f; - } + PlayerStats(void): ps_iScore(0), ps_iKills(0), ps_iDeaths(0), ps_iSecrets(0), ps_tmTime(0.0f){} }; static inline CTStream &operator>>(CTStream &strm, PlayerStats &ps) diff --git a/Sources/EntitiesMP/Common/HUD.cpp b/Sources/EntitiesMP/Common/HUD.cpp index f519865..60a9756 100755 --- a/Sources/EntitiesMP/Common/HUD.cpp +++ b/Sources/EntitiesMP/Common/HUD.cpp @@ -1180,7 +1180,7 @@ extern void DrawHUD( const CPlayer *penPlayerCurrent, CDrawPort *pdpCurrent, BOO if( iHealth>25) colHealth = _colHUD; if( iArmor >25) colArmor = _colHUD; // eventually print it out - if( hud_iShowPlayers==1 || (hud_iShowPlayers==-1 && !bSinglePlay)) { + if( hud_iShowPlayers==1 || hud_iShowPlayers==-1) { // printout location and info aren't the same for deathmatch and coop play const FLOAT fCharWidth = (PIX)((_pfdDisplayFont->GetWidth()-2) *fTextScale); if( bCooperative) { diff --git a/Sources/EntitiesMP/Common/Particles.cpp b/Sources/EntitiesMP/Common/Particles.cpp index d8ad616..4a0841e 100755 --- a/Sources/EntitiesMP/Common/Particles.cpp +++ b/Sources/EntitiesMP/Common/Particles.cpp @@ -2284,9 +2284,8 @@ void Particles_MetalParts( CEntity *pen, FLOAT tmStarted, FLOATaabbox3D boxOwner UBYTE ubRndH = UBYTE( 180+afStarsPositions[ int(iPart+tmStarted*10)%CT_MAX_PARTICLES_TABLE][0]*16); UBYTE ubRndS = UBYTE( 12+(afStarsPositions[ int(iPart+tmStarted*10)%CT_MAX_PARTICLES_TABLE][1])*8); - UBYTE ubRndV = UBYTE( 192+(afStarsPositions[ int(iPart+tmStarted*10)%CT_MAX_PARTICLES_TABLE][2])*64); //ubRndS = 0; - ubRndV = 255; + UBYTE ubRndV = 255; COLOR col = HSVToColor(ubRndH, ubRndS, ubRndV)|UBYTE(255.0f*fRatio); FLOAT fRotation = fT*400.0f*afStarsPositions[iRnd][0]; FLOAT fSize = fBoxSize*0.005f+0.125f+afStarsPositions[iRnd][1]*0.025f; @@ -4502,10 +4501,8 @@ void Particles_BloodSpray(enum SprayParticlesType sptType, FLOAT3D vSource, FLOA case SPT_ELECTRICITY_SPARKS: { UBYTE ubRndH = UBYTE( 180+afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][0]*16); - UBYTE ubRndS = UBYTE( 32+(afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][1]+0.5)*16); - UBYTE ubRndV = UBYTE( 192+(afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][2])*64); - ubRndS = 0; - ubRndV = 255; + UBYTE ubRndS = 0; + UBYTE ubRndV = 255; col = HSVToColor(ubRndH, ubRndS, ubRndV)|ubAlpha; fSize/=32.0f; fRotation = fT*200.0f; diff --git a/Sources/GameMP/Game.cpp b/Sources/GameMP/Game.cpp index 06584b6..9e58ca6 100755 --- a/Sources/GameMP/Game.cpp +++ b/Sources/GameMP/Game.cpp @@ -188,8 +188,7 @@ public: ~CEnableUserBreak(); }; -CEnableUserBreak::CEnableUserBreak() { - bOld = _bUserBreakEnabled; +CEnableUserBreak::CEnableUserBreak(): bOld(_bUserBreakEnabled){ _bUserBreakEnabled = TRUE; } CEnableUserBreak::~CEnableUserBreak() { diff --git a/Sources/GameMP/Game.h b/Sources/GameMP/Game.h index 5821ae2..0d61987 100644 --- a/Sources/GameMP/Game.h +++ b/Sources/GameMP/Game.h @@ -139,10 +139,8 @@ public: CPlayerSource *lp_pplsPlayerSource; UBYTE lp_ubPlayerControlsState[2048]; // current state of player controls that are local to the player // Construction - CLocalPlayer( void) + CLocalPlayer(void): lp_pplsPlayerSource(NULL), lp_bActive(FALSE) { - lp_pplsPlayerSource = NULL; - lp_bActive = FALSE; memset(lp_ubPlayerControlsState, 0, sizeof(lp_ubPlayerControlsState)) ; }; };