1#pragma once 2 3//******************************************************************************************** 4//* 5//* This file is part of Egoboo. 6//* 7//* Egoboo is free software: you can redistribute it and/or modify it 8//* under the terms of the GNU General Public License as published by 9//* the Free Software Foundation, either version 3 of the License, or 10//* (at your option) any later version. 11//* 12//* Egoboo is distributed in the hope that it will be useful, but 13//* WITHOUT ANY WARRANTY; without even the implied warranty of 14//* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15//* General Public License for more details. 16//* 17//* You should have received a copy of the GNU General Public License 18//* along with Egoboo. If not, see <http://www.gnu.org/licenses/>. 19//* 20//******************************************************************************************** 21 22#include "PrtList.h" 23 24#include "char.inl" 25 26//-------------------------------------------------------------------------------------------- 27// FORWARD DECLARATION 28//-------------------------------------------------------------------------------------------- 29 30static INLINE PIP_REF prt_get_ipip( const PRT_REF particle ); 31static INLINE pip_t * prt_get_ppip( const PRT_REF particle ); 32static INLINE CHR_REF prt_get_iowner( const PRT_REF iprt, int depth ); 33static INLINE bool_t prt_set_size( prt_t *, int size ); 34static INLINE float prt_get_scale( prt_t * pprt ); 35 36static INLINE prt_bundle_t * prt_bundle_ctor( prt_bundle_t * pbundle ); 37static INLINE prt_bundle_t * prt_bundle_validate( prt_bundle_t * pbundle ); 38static INLINE prt_bundle_t * prt_bundle_set( prt_bundle_t * pbundle, prt_t * pprt ); 39 40static INLINE float * prt_get_pos_v( prt_t * pprt ); 41static INLINE fvec3_t prt_get_pos( prt_t * pprt ); 42 43//-------------------------------------------------------------------------------------------- 44// IMPLEMENTATION 45//-------------------------------------------------------------------------------------------- 46static INLINE PIP_REF prt_get_ipip( const PRT_REF iprt ) 47{ 48 prt_t * pprt; 49 50 if ( !DEFINED_PRT( iprt ) ) return ( PIP_REF )MAX_PIP; 51 pprt = PrtList.lst + iprt; 52 53 if ( !LOADED_PIP( pprt->pip_ref ) ) return ( PIP_REF )MAX_PIP; 54 55 return pprt->pip_ref; 56} 57 58//-------------------------------------------------------------------------------------------- 59static INLINE pip_t * prt_get_ppip( const PRT_REF iprt ) 60{ 61 prt_t * pprt; 62 63 if ( !DEFINED_PRT( iprt ) ) return NULL; 64 pprt = PrtList.lst + iprt; 65 66 if ( !LOADED_PIP( pprt->pip_ref ) ) return NULL; 67 68 return PipStack.lst + pprt->pip_ref; 69} 70 71//-------------------------------------------------------------------------------------------- 72static INLINE bool_t prt_set_size( prt_t * pprt, int size ) 73{ 74 pip_t *ppip; 75 76 if ( !DEFINED_PPRT( pprt ) ) return bfalse; 77 78 if ( !LOADED_PIP( pprt->pip_ref ) ) return bfalse; 79 ppip = PipStack.lst + pprt->pip_ref; 80 81 // set the graphical size 82 pprt->size = size; 83 84 // set the bumper size, if available 85 if ( 0 == pprt->bump_size_stt ) 86 { 87 // make the particle non-interacting if the initial bumper size was 0 88 pprt->bump_real.size = 0; 89 pprt->bump_padded.size = 0; 90 } 91 else 92 { 93 float real_size = FP8_TO_FLOAT( size ) * prt_get_scale( pprt ); 94 95 if ( 0.0f == pprt->bump_real.size || 0.0f == size ) 96 { 97 // just set the size, assuming a spherical particle 98 pprt->bump_real.size = real_size; 99 pprt->bump_real.size_big = real_size * SQRT_TWO; 100 pprt->bump_real.height = real_size; 101 } 102 else 103 { 104 float mag = real_size / pprt->bump_real.size; 105 106 // resize all dimensions equally 107 pprt->bump_real.size *= mag; 108 pprt->bump_real.size_big *= mag; 109 pprt->bump_real.height *= mag; 110 } 111 112 // make sure that the virtual bumper size is at least as big as what is in the pip file 113 pprt->bump_padded.size = MAX( pprt->bump_real.size, ppip->bump_size ); 114 pprt->bump_padded.size_big = MAX( pprt->bump_real.size_big, ppip->bump_size * SQRT_TWO ); 115 pprt->bump_padded.height = MAX( pprt->bump_real.height, ppip->bump_height ); 116 } 117 118 // set the real size of the particle 119 oct_bb_set_bumper( &( pprt->prt_min_cv ), pprt->bump_real ); 120 121 // use the padded bumper to figure out the chr_max_cv 122 oct_bb_set_bumper( &( pprt->prt_max_cv ), pprt->bump_padded ); 123 124 return btrue; 125} 126 127//-------------------------------------------------------------------------------------------- 128static INLINE CHR_REF prt_get_iowner( const PRT_REF iprt, int depth ) 129{ 130 /// BB@> A helper function for determining the owner of a paricle 131 /// 132 /// @details There could be a possibility that a particle exists that was spawned by 133 /// another particle, but has lost contact with its original spawner. For instance 134 /// If an explosion particle bounces off of something with MISSILE_DEFLECT or 135 /// MISSILE_REFLECT, which subsequently dies before the particle... 136 /// 137 /// That is actually pretty far fetched, but at some point it might make sense to 138 /// spawn particles just keeping track of the spawner (whether particle or character) 139 /// and working backward to any potential owner using this function. ;) 140 /// 141 /// @note this function should be completely trivial for anything other than 142 /// namage particles created by an explosion 143 144 CHR_REF iowner = ( CHR_REF )MAX_CHR; 145 146 prt_t * pprt; 147 148 // be careful because this can be recursive 149 if ( depth > ( int )maxparticles - ( int )PrtList.free_count ) return ( CHR_REF )MAX_CHR; 150 151 if ( !DEFINED_PRT( iprt ) ) return ( CHR_REF )MAX_CHR; 152 pprt = PrtList.lst + iprt; 153 154 if ( DEFINED_CHR( pprt->owner_ref ) ) 155 { 156 iowner = pprt->owner_ref; 157 } 158 else 159 { 160 // make a check for a stupid looping structure... 161 // cannot be sure you could never get a loop, though 162 163 if ( !ALLOCATED_PRT( pprt->parent_ref ) ) 164 { 165 // make sure that a non valid parent_ref is marked as non-valid 166 pprt->parent_ref = MAX_PRT; 167 pprt->parent_guid = 0xFFFFFFFF; 168 } 169 else 170 { 171 // if a particle has been poofed, and another particle lives at that address, 172 // it is possible that the pprt->parent_ref points to a valid particle that is 173 // not the parent. Depending on how scrambled the list gets, there could actually 174 // be looping structures. I have actually seen this, so don't laugh :) 175 176 if ( PrtList.lst[pprt->parent_ref].obj_base.guid == pprt->parent_guid ) 177 { 178 if ( iprt != pprt->parent_ref ) 179 { 180 iowner = prt_get_iowner( pprt->parent_ref, depth + 1 ); 181 } 182 } 183 else 184 { 185 // the parent particle doesn't exist anymore 186 // fix the reference 187 pprt->parent_ref = MAX_PRT; 188 pprt->parent_guid = 0xFFFFFFFF; 189 } 190 } 191 } 192 193 return iowner; 194} 195 196//-------------------------------------------------------------------------------------------- 197static INLINE float prt_get_scale( prt_t * pprt ) 198{ 199 /// @details BB@> get the scale factor between the "graphical size" of the particle and the actual 200 /// display size 201 202 float scale = 0.25f; 203 204 if ( !DEFINED_PPRT( pprt ) ) return scale; 205 206 // set some particle dependent properties 207 switch ( pprt->type ) 208 { 209 case SPRITE_SOLID: scale *= 0.9384f; break; 210 case SPRITE_ALPHA: scale *= 0.9353f; break; 211 case SPRITE_LIGHT: scale *= 1.5912f; break; 212 } 213 214 return scale; 215} 216 217//-------------------------------------------------------------------------------------------- 218//-------------------------------------------------------------------------------------------- 219static INLINE prt_bundle_t * prt_bundle_ctor( prt_bundle_t * pbundle ) 220{ 221 if ( NULL == pbundle ) return NULL; 222 223 pbundle->prt_ref = ( PRT_REF ) MAX_PRT; 224 pbundle->prt_ptr = NULL; 225 226 pbundle->pip_ref = ( PIP_REF ) MAX_PIP; 227 pbundle->pip_ptr = NULL; 228 229 return pbundle; 230} 231 232//-------------------------------------------------------------------------------------------- 233static INLINE prt_bundle_t * prt_bundle_validate( prt_bundle_t * pbundle ) 234{ 235 if ( NULL == pbundle ) return NULL; 236 237 if ( ALLOCATED_PRT( pbundle->prt_ref ) ) 238 { 239 pbundle->prt_ptr = PrtList.lst + pbundle->prt_ref; 240 } 241 else if ( NULL != pbundle->prt_ptr ) 242 { 243 pbundle->prt_ref = GET_REF_PPRT( pbundle->prt_ptr ); 244 } 245 else 246 { 247 pbundle->prt_ref = MAX_PRT; 248 pbundle->prt_ptr = NULL; 249 } 250 251 if ( !LOADED_PIP( pbundle->pip_ref ) && NULL != pbundle->prt_ptr ) 252 { 253 pbundle->pip_ref = pbundle->prt_ptr->pip_ref; 254 } 255 256 if ( LOADED_PIP( pbundle->pip_ref ) ) 257 { 258 pbundle->pip_ptr = PipStack.lst + pbundle->pip_ref; 259 } 260 else 261 { 262 pbundle->pip_ref = ( PIP_REF ) MAX_PIP; 263 pbundle->pip_ptr = NULL; 264 } 265 266 return pbundle; 267} 268 269//-------------------------------------------------------------------------------------------- 270static INLINE prt_bundle_t * prt_bundle_set( prt_bundle_t * pbundle, prt_t * pprt ) 271{ 272 if ( NULL == pbundle ) return NULL; 273 274 // blank out old data 275 pbundle = prt_bundle_ctor( pbundle ); 276 277 if ( NULL == pbundle || NULL == pprt ) return pbundle; 278 279 // set the particle pointer 280 pbundle->prt_ptr = pprt; 281 282 // validate the particle data 283 pbundle = prt_bundle_validate( pbundle ); 284 285 return pbundle; 286} 287 288//-------------------------------------------------------------------------------------------- 289fvec3_t prt_get_pos( prt_t * pprt ) 290{ 291 fvec3_t vtmp = ZERO_VECT3; 292 293 if ( !ALLOCATED_PPRT( pprt ) ) return vtmp; 294 295 return pprt->pos; 296} 297 298//-------------------------------------------------------------------------------------------- 299float * prt_get_pos_v( prt_t * pprt ) 300{ 301 static fvec3_t vtmp = ZERO_VECT3; 302 303 if ( !ALLOCATED_PPRT( pprt ) ) return vtmp.v; 304 305 return pprt->pos.v; 306} 307 308//-------------------------------------------------------------------------------------------- 309//-------------------------------------------------------------------------------------------- 310 311#define _particle_inl