/* ------------------------------------------------------------------------------------ */ int CCameraManager::GetPosition(geVec3d *thePosition) { // changed RF063 geXForm3d theViewPoint; // changed QD 12/15/05 //geXForm3d_SetIdentity(&theViewPoint); // Clear the matrix //geXForm3d_RotateZ(&theViewPoint, Rotation.Z); // Rotate then translate geXForm3d_SetZRotation(&theViewPoint, Rotation.Z); // end change geXForm3d_RotateX(&theViewPoint, Rotation.X); geXForm3d_RotateY(&theViewPoint, Rotation.Y); geXForm3d_Translate(&theViewPoint, Translation.X, Translation.Y, Translation.Z); if(jerk) { geVec3d Direction; geXForm3d_GetIn(&theViewPoint, &Direction); geVec3d_AddScaled(&theViewPoint.Translation, &Direction, -jerkamt, &theViewPoint.Translation); } //*thePosition = Translation; *thePosition = theViewPoint.Translation; // end change RF063 return RGF_SUCCESS; }
//================================================================================ // Frustum_TransformToWorldSpace //================================================================================ void Frustum_TransformToWorldSpace(const Frustum_Info *In, const geCamera *Camera, Frustum_Info *Out) { int32 i; GFX_Plane *pPlane1, *pPlane2; assert(In != Out); pPlane1 = (GFX_Plane*)In->Planes; pPlane2 = Out->Planes; // Rotate all the planes for (i=0; i<In->NumPlanes; i++, pPlane1++, pPlane2++) { pPlane2->Type = pPlane1->Type; SetWorldspaceClipPlane(pPlane1, Camera, pPlane2); pPlane2->Dist = geVec3d_DotProduct(geCamera_GetPov(Camera), &pPlane2->Normal) - CLIP_PLANE_EPSILON; if (pPlane1->Dist) // Add the original dist back in { geVec3d Vect; geVec3d_Clear(&Vect); geVec3d_AddScaled(&Vect, &pPlane1->Normal, pPlane1->Dist, &Vect); BackRotateVector(&Vect, &Vect, geCamera_GetCameraSpaceXForm(Camera)); pPlane2->Dist += geVec3d_DotProduct(&pPlane2->Normal, &Vect); } } Out->NumPlanes = In->NumPlanes; // Get BBox info for fast BBox rejection against frustum... SetUpFrustumBBox(Out); }
geBoolean TestEdge_r(geFloat Start, geFloat End, int32 p1, int32 p2, int32 StartVert) { int32 j, k; geFloat Dist; geVec3d Delta; geVec3d Exact; geVec3d Off; geFloat Error; geVec3d p; if (p1 == p2) { //GHook.Printf("TestEdge_r: Degenerate Edge.\n"); return GE_TRUE; // degenerate edge } for (k=StartVert ; k<NumEdgeVerts ; k++) { j = EdgeVerts[k]; if (j==p1 || j == p2) continue; p = WeldedVerts[j]; geVec3d_Subtract(&p, &EdgeStart, &Delta); Dist = geVec3d_DotProduct(&Delta, &EdgeDir); if (Dist <= Start || Dist >= End) continue; geVec3d_AddScaled(&EdgeStart, &EdgeDir, Dist, &Exact); geVec3d_Subtract(&p, &Exact, &Off); Error = geVec3d_Length(&Off); if (fabs(Error) > OFF_EPSILON) continue; // break the edge NumTJunctions++; TestEdge_r (Start, Dist, p1, j, k+1); TestEdge_r (Dist, End, j, p2, k+1); return GE_TRUE; } if (NumTempIndexVerts >= MAX_TEMP_INDEX_VERTS) { GHook.Error("Max Temp Index Verts.\n"); return GE_FALSE; } TempIndexVerts[NumTempIndexVerts] = p1; NumTempIndexVerts++; return GE_TRUE; }
void weapon_mini_rocket_proccess(float timePassed){ #define COLLISION geWorld_Collision(mini_rocketCurrentWorld,&(g->box.Min),&(g->box.Max),&(g->position),&newPos,GE_CONTENTS_SOLID_CLIP,GE_COLLIDE_ALL,0xffffffff, cb_move, 0, &lCol) int i; InfMiniRocket* g; geVec3d newPos; geVec3d to; geVec3d angles; GE_Collision lCol; for( i=0; i<NUMBER_OF_MINIROCKETS; i++){ g = & miniRockets[i]; if( g->active ){ geVec3d_AddScaled(&(g->position), &(g->velocity), timePassed, &(newPos) ); if( COLLISION ) { g->position = lCol.Impact; //geVec3d_Scale(&(g->velocity), -0.8f, &(g->velocity) ); weapon_mini_rocket_destroy(g); } else { g->position = newPos; } geVec3d_Add(&(g->position), &(g->velocity), &to); LookAt(g->position, to, &angles); angles.X += GE_PI/2; // update xform variable geXForm3d_SetIdentity(&(g->xform)); geXForm3d_RotateX(&(g->xform), angles.X); geXForm3d_RotateY(&(g->xform), angles.Y); geXForm3d_RotateZ(&(g->xform), angles.Z); g->xform.Translation = g->position; geActor_ClearPose(g->mini_rocket, &(g->xform) ); } } #undef COLLISION }
/* ------------------------------------------------------------------------------------ */ int CRain::Create(Rain *R) { int effect = -1; Spray Sp; // clear out spray data memset(&Sp, 0, sizeof(Sp)); // get bitmap for use as texture // rain/a_rain are default bitmap names Sp.Texture = TPool_Bitmap("rain.bmp", "a_rain.bmp", R->BmpName, R->AlphaName); // setup spray data Sp.MinScale = 0.5f; Sp.MaxScale = 1.5f; Sp.ShowAlways = GE_TRUE; Sp.Rate = (1.1f - R->Severity)*0.1f; geVec3d_Copy(&(R->Gravity), &(Sp.Gravity)); // set source position geVec3d_Copy(&(R->origin), &(Sp.Source)); Sp.SourceVariance = (int)(R->Radius*0.5f); Sp.MinUnitLife = R->DropLife; Sp.MaxUnitLife = R->DropLife; // set destination position geVec3d_AddScaled(&(Sp.Source), &(Sp.Gravity), Sp.MinUnitLife, &(Sp.Dest)); Sp.DestVariance = (int)(R->Radius*0.5f); memcpy(&(Sp.ColorMin), &(R->ColorMin), sizeof(Sp.ColorMin)); memcpy(&(Sp.ColorMax), &(R->ColorMax), sizeof(Sp.ColorMax)); Sp.ColorMin.a = Sp.ColorMax.a = 255.0f; Sp.UseWind = R->UseWind; effect = CCD->EffectManager()->Item_Add(EFF_SPRAY, (void*)&Sp); return effect; }
void weapon_molotov_proccess(float timePassed){ #define COLLISION geWorld_Collision(molotovCurrentWorld,&(m->box.Min),&(m->box.Max),&(m->position),&newPos,GE_CONTENTS_SOLID_CLIP,GE_COLLIDE_ALL,0xffffffff, cb_move, 0, &lCol) int i; InfMolotov* m; geVec3d newPos; GE_Collision lCol; for( i=0; i<NUMBER_OF_MOLOTOVS; i++){ m = & molotovs[i]; if( m->active ){ m->velocity.Y -= GRAVITY *timePassed; geVec3d_AddScaled(&(m->position), &(m->velocity), timePassed, &(newPos) ); if( COLLISION ) { m->position = lCol.Impact; weapon_molotov_destroy(m); //geVec3d_Scale(&(m->velocity), -0.8f, &(m->velocity) ); //geVec3d_Reflect(&(m->velocity), &(lCol.Plane.Normal), &(m->velocity), 0.60f); } else { m->position = newPos; } /* if( m->timeLeftToBang <= 0.0f ){ weapon_molotov_destroy(m); return; }*/ // update xform variable geXForm3d_SetIdentity(&(m->xform)); m->xform.Translation = m->position; geActor_ClearPose(m->molotov, &(m->xform) ); } } #undef COLLISION }
//================================================================================ // Frustum_RotateToWorldSpace //================================================================================ void Frustum_RotateToWorldSpace(Frustum_Info *In, geCamera *Camera, Frustum_Info *Out) { int32 i; GFX_Plane *pPlane1, *pPlane2; assert(In != Out); pPlane1 = In->Planes; pPlane2 = Out->Planes; // Rotate all the planes for (i=0; i<In->NumPlanes; i++, pPlane1++, pPlane2++) { pPlane2->Type = pPlane1->Type; SetWorldspaceClipPlane(pPlane1, Camera, pPlane2); pPlane2->Dist = 0.0f; // We are just rotating, so set dist to 0 if (pPlane1->Dist) // Add the original dist back in { geVec3d Vect; geVec3d_Clear(&Vect); geVec3d_AddScaled(&Vect, &pPlane1->Normal, pPlane1->Dist, &Vect); BackRotateVector(&Vect, &Vect, geCamera_GetCameraSpaceXForm(Camera)); pPlane2->Dist += geVec3d_DotProduct(&pPlane2->Normal, &Vect); } } Out->NumPlanes = In->NumPlanes; // Get BBox info for fast BBox rejection against frustum... SetUpFrustumBBox(Out); }
/* ------------------------------------------------------------------------------------ */ int CCameraManager::RenderView() { geXForm3d theViewPoint; // changed QD 12/15/05 //geXForm3d_SetIdentity(&theViewPoint); // Clear the matrix //geXForm3d_RotateZ(&theViewPoint, Rotation.Z); // Rotate then translate geXForm3d_SetZRotation(&theViewPoint, Rotation.Z); // end change geXForm3d_RotateX(&theViewPoint, Rotation.X); geXForm3d_RotateY(&theViewPoint, Rotation.Y); geXForm3d_Translate(&theViewPoint, Translation.X+shakex, Translation.Y+shakey, Translation.Z); // changed RF063 GE_Contents ZoneContents; geExtBox ExtBox; geVec3d Direction, Pos; GE_LVertex Vertex; ExtBox.Min.X = ExtBox.Min.Z = -1.0f; ExtBox.Min.Y = 0.0f; ExtBox.Max.Y = 1.0f; ExtBox.Max.X = ExtBox.Max.Z = 1.0f; if(CCD->Collision()->GetContentsOf(Translation, &ExtBox, &ZoneContents) == RGF_SUCCESS) //if(geWorld_GetContents(CCD->World(), &Translation, &ExtBox.Min, //&ExtBox.Max, GE_COLLIDE_MODELS, 0, NULL, NULL, &ZoneContents) == GE_TRUE) { Liquid * LQ = CCD->Liquids()->IsLiquid(ZoneContents.Model); if(LQ) { geXForm3d_GetIn(&theViewPoint, &Direction); geVec3d_AddScaled(&Translation, &Direction, OverlayDist, &Pos); Vertex.r = LQ->TintColor.r; Vertex.g = LQ->TintColor.g; Vertex.b = LQ->TintColor.b; Vertex.a = LQ->Transparency; Vertex.u = 0.0f; Vertex.v = 0.0f; Vertex.X = Pos.X; Vertex.Y = Pos.Y; Vertex.Z = Pos.Z; geWorld_AddPolyOnce(CCD->World(), &Vertex, 1, LQ->Texture, GE_TEXTURED_POINT , GE_RENDER_DO_NOT_OCCLUDE_SELF, 2.0f ); } // changed RF064 else { Overlay * OL = CCD->Overlays()->IsOverlay(ZoneContents.Model); if(OL) { geXForm3d_GetIn(&theViewPoint, &Direction); geVec3d_AddScaled(&Translation, &Direction, OverlayDist, &Pos); Vertex.r = OL->TintColor.r; Vertex.g = OL->TintColor.g; Vertex.b = OL->TintColor.b; Vertex.a = OL->Transparency; Vertex.u = 0.0f; Vertex.v = 0.0f; Vertex.X = Pos.X; Vertex.Y = Pos.Y; Vertex.Z = Pos.Z; geWorld_AddPolyOnce(CCD->World(), &Vertex, 1, OL->Texture, GE_TEXTURED_POINT , GE_RENDER_DO_NOT_OCCLUDE_SELF, 2.0f); } } // end change RF064 } if(jerk) { geVec3d Direction; geXForm3d_GetIn(&theViewPoint, &Direction); geVec3d_AddScaled(&theViewPoint.Translation, &Direction, -jerkamt, &theViewPoint.Translation); } // end change RF063 // Set up camera attributes just prior to rendering the world. geRect Rect; geCamera_SetWorldSpaceXForm(EngineCamera, &theViewPoint); geCamera_GetClippingRect(EngineCamera, &Rect); geCamera_SetAttributes(EngineCamera, FOV, &Rect); // changed RF064 geVec3d_Subtract(&m_OldXForm.Translation, &theViewPoint.Translation, &m_vMoveDif ); m_bPositionMoved = !geVec3d_IsZero(&m_vMoveDif); if( m_bPositionMoved || m_OldXForm.AX != theViewPoint.AX || m_OldXForm.AY != theViewPoint.AY || m_OldXForm.AZ != theViewPoint.AZ || m_OldXForm.BX != theViewPoint.BX || m_OldXForm.BY != theViewPoint.BY || m_OldXForm.BZ != theViewPoint.BZ || m_OldXForm.CX != theViewPoint.CX || m_OldXForm.CY != theViewPoint.CY || m_OldXForm.CZ != theViewPoint.CZ) { m_bViewChanged = true; m_OldXForm = theViewPoint; } // end change RF064 return RGF_SUCCESS; }
/* ------------------------------------------------------------------------------------ */ void CCameraManager::DoIsoTracking() { geXForm3d theViewPoint; geVec3d Pos; GE_Collision Collision; geVec3d Front, Back; geVec3d Direction; geFloat CurrentDistance; geExtBox ActorExtBox; geFloat ActorScale; geVec3d Orient; geFloat x; CCD->ActorManager()->GetScale(theActor, &ActorScale); // Get actor scale CCD->ActorManager()->GetBoundingBox(theActor, &ActorExtBox); CurrentDistance = m_defaultdistance * ActorScale; geVec3d ActorPosition, ActorRotation; CCD->ActorManager()->GetPosition(theActor, &ActorPosition); ActorPosition.Y += CameraOffsetTranslation.Y; CCD->ActorManager()->GetRotation(theActor, &ActorRotation); ActorRotation.X = 0.0f; // changed QD 12/15/05 //geXForm3d_SetIdentity(&theViewPoint); //geXForm3d_RotateZ(&theViewPoint, CameraOffsetRotation.Z); geXForm3d_SetZRotation(&theViewPoint, CameraOffsetRotation.Z); // end change geXForm3d_RotateX(&theViewPoint, CameraOffsetRotation.X+GE_PIOVER180*(m_cameraX)); geXForm3d_RotateY(&theViewPoint, CameraOffsetRotation.Y+GE_PIOVER180*(m_cameraY)); geXForm3d_Translate(&theViewPoint, ActorPosition.X, ActorPosition.Y, ActorPosition.Z); Pos = theViewPoint.Translation; geXForm3d_GetIn(&theViewPoint, &Direction); geVec3d_AddScaled(&Pos, &Direction, CurrentDistance, &Back); // changed QD 12/15/05 // geVec3d_AddScaled(&Pos, &Direction, 0.0f, &Front); geVec3d_Copy(&Pos, &Front); // end change if(IsoCollFlag) { if(geWorld_Collision(CCD->World(), &CameraExtBox.Min, &CameraExtBox.Max, &Front, &Back, /*GE_VISIBLE_CONTENTS*/GE_CONTENTS_SOLID_CLIP, GE_COLLIDE_ALL, 0, NULL, NULL, &Collision)) { // changed QD 01/2004 // can't be negative (sqrt) // CurrentDistance = (geFloat)fabs(geVec3d_DistanceBetween(&Collision.Impact, &Front)); // if(CurrentDistance < 0.0f) // CurrentDistance = 0.0f; CurrentDistance = geVec3d_DistanceBetween(&Collision.Impact, &Front); // end change if(CurrentDistance > (m_defaultdistance*ActorScale)) CurrentDistance = m_defaultdistance*ActorScale; geVec3d_AddScaled(&Pos, &Direction, CurrentDistance, &Back); } // changed QD 01/2004 if(CCD->Meshes()->CollisionCheck(&CameraExtBox.Min, &CameraExtBox.Max, Front, Back, &Collision)) { geFloat CurrentDistance2 = geVec3d_DistanceBetween(&Collision.Impact, &Front); if(CurrentDistance2 > (m_defaultdistance*ActorScale)) CurrentDistance2 = m_defaultdistance*ActorScale; if(CurrentDistance2<CurrentDistance) { CurrentDistance = CurrentDistance2; geVec3d_AddScaled(&Pos, &Direction, CurrentDistance2, &Back); } } // end change } m_currentdistance = CurrentDistance/ActorScale; if(IsoCollFlag) { geFloat fAlpha = 255.0f; if(CurrentDistance < (40.0f*ActorScale)) { fAlpha = (10.0f*((CurrentDistance-((geFloat)fabs(ActorExtBox.Min.Z)+1.0f))/ActorScale))+30.0f; if(fAlpha < (15.0f*ActorScale)) fAlpha = 0.0f; if(fAlpha > 255.0f) fAlpha = 255.0f; } CCD->ActorManager()->SetAlpha(theActor, fAlpha); // Adjust actor alpha } geVec3d_Subtract( &Pos, &Back, &Orient ); // protect from Div by Zero if(CurrentDistance > 0.0f) { x = Orient.X; // changed QD 12/15/05 // Orient.X = GE_PI*0.5f - (geFloat)acos(Orient.Y / CurrentDistance); Orient.X = GE_PIOVER2 - (geFloat)acos(Orient.Y / CurrentDistance); Orient.Y = (geFloat)atan2(x, Orient.Z) + GE_PI; Orient.Z = 0.0f; // roll is zero - always!!? } Rotation = Orient; // Set camera orientation Translation = Back; // Set camera translation return; }
/* ------------------------------------------------------------------------------------ */ void CCameraManager::DoThirdPersonTracking() { geXForm3d theViewPoint; geVec3d Pos; GE_Collision Collision; geVec3d Front, Back; geVec3d Direction; geFloat CurrentDistance; geExtBox ActorExtBox; geFloat ActorScale; geVec3d Orient; geFloat x; // changed QD 01/2004 geFloat PlayerScale = CCD->Player()->GetScale(); // end change CCD->ActorManager()->GetScale(theActor, &ActorScale); // Get actor scale CCD->ActorManager()->GetBoundingBox(theActor, &ActorExtBox); CurrentDistance = m_defaultdistance * ActorScale; geVec3d ActorPosition, ActorRotation; CCD->ActorManager()->GetPosition(theActor, &ActorPosition); ActorPosition.Y += CameraOffsetTranslation.Y; CCD->ActorManager()->GetRotation(theActor, &ActorRotation); // Start Nov2003DCS geVec3d_Add(&ActorRotation, &CameraOffsetRotation, &ActorRotation); // End Nov2003DCS ActorRotation.X = 0.0f; // changed QD 12/15/05 //geXForm3d_SetIdentity(&theViewPoint); //geXForm3d_RotateZ(&theViewPoint, ActorRotation.Z+CameraOffsetRotation.Z); geXForm3d_SetZRotation(&theViewPoint, ActorRotation.Z+CameraOffsetRotation.Z); // end change geXForm3d_RotateX(&theViewPoint, ActorRotation.X+CameraOffsetRotation.X+GE_PIOVER180*(m_cameraX)); geXForm3d_RotateY(&theViewPoint, ActorRotation.Y+CameraOffsetRotation.Y+GE_PIOVER180*(m_cameraY)); geXForm3d_Translate(&theViewPoint, ActorPosition.X, ActorPosition.Y, ActorPosition.Z); Pos = theViewPoint.Translation; geXForm3d_GetIn(&theViewPoint, &Direction); geVec3d_AddScaled(&Pos, &Direction, CurrentDistance, &Back); // changed QD 12/15/05 // geVec3d_AddScaled(&Pos, &Direction, 0.0f, &Front); geVec3d_Copy(&Pos, &Front); // end change if(geWorld_Collision(CCD->World(), &CameraExtBox.Min, &CameraExtBox.Max, &Front, &Back, /*GE_VISIBLE_CONTENTS*/GE_CONTENTS_SOLID_CLIP, GE_COLLIDE_ALL, 0, NULL, NULL, &Collision)) { // changed QD 01/2004 // can't be negative (sqrt!) // CurrentDistance = (geFloat)fabs(geVec3d_DistanceBetween(&Collision.Impact, &Front)); // if(CurrentDistance < 0.0f) // CurrentDistance = 0.0f; CurrentDistance = geVec3d_DistanceBetween(&Collision.Impact, &Front); // end change if(CurrentDistance > (m_defaultdistance*ActorScale)) CurrentDistance = m_defaultdistance*ActorScale; geVec3d_AddScaled(&Pos, &Direction, CurrentDistance, &Back); } // changed QD 01/2004 geVec3d_AddScaled(&Pos, &Direction, playermindistance*ActorScale, &Front); if(CCD->Meshes()->CollisionCheck(&CameraExtBox.Min, &CameraExtBox.Max, Front, Back, &Collision)) { // changed QD distance can't be negative // geFloat CurrentDistance2 = (geFloat)fabs(geVec3d_DistanceBetween(&Collision.Impact, &Front));//-4.0f; geFloat CurrentDistance2 = geVec3d_DistanceBetween(&Collision.Impact, &Front); CurrentDistance2 += playermindistance*ActorScale; if(theActor == CCD->Player()->GetActor()) { if(CurrentDistance2 < (playermindistance*ActorScale)) CurrentDistance2 = playermindistance*ActorScale; if(CurrentDistance2 > (playermaxdistance*ActorScale)) CurrentDistance2 = playermaxdistance*ActorScale; } else { if(CurrentDistance2 > (m_defaultdistance*ActorScale)) CurrentDistance2 = m_defaultdistance*ActorScale; } if(CurrentDistance2 < CurrentDistance) { CurrentDistance = CurrentDistance2; geVec3d_AddScaled(&Pos, &Direction, CurrentDistance2, &Back); } } // end change m_currentdistance = CurrentDistance/ActorScale; // Ok, here's the implementation of Ralph Deane's too-cool // ..third-person Actor Fading code. As the camera approaches // ..the player avatar, the AVATAR IS FADED OUT until finally // ..it's rendering is shut down. This is one Way Cool Effect. // 03/22/2000 eaa3 Added Ralph Deane's scaling fixes. geFloat fAlpha = 255.0f; if(CurrentDistance < (40.0f*ActorScale)) { fAlpha = (10.0f*((CurrentDistance-((geFloat)fabs(ActorExtBox.Min.Z)+1.0f))/ActorScale))+30.0f; if(fAlpha < (15.0f*ActorScale)) fAlpha = 0.0f; if(fAlpha > 255.0f) fAlpha = 255.0f; } CCD->ActorManager()->SetAlpha(theActor, fAlpha); // Adjust actor alpha geVec3d_Subtract( &Pos, &Back, &Orient ); // protect from Div by Zero if(CurrentDistance > 0.0f) { x = Orient.X; // changed QD 12/15/05 // Orient.X = (geFloat)( GE_PI*0.5 ) - (geFloat)acos(Orient.Y / CurrentDistance); Orient.X = GE_PIOVER2 - (geFloat)acos(Orient.Y / CurrentDistance); Orient.Y = (geFloat)atan2(x, Orient.Z) + GE_PI; Orient.Z = 0.0f; // roll is zero - always!!? } Rotation = Orient; // Set camera orientation Translation = Back; // Set camera translation return; }
/* ------------------------------------------------------------------------------------ */ void CRain::Tick(geFloat dwTicks) { geEntity_EntitySet *pSet; geEntity *pEntity; int i; Spray Sp; pSet = geWorld_GetEntitySet(CCD->World(), "Rain"); if(!pSet) return; for(pEntity=geEntity_EntitySetGetNextEntity(pSet, NULL); pEntity; pEntity=geEntity_EntitySetGetNextEntity(pSet, pEntity)) { Rain *R = (Rain*)geEntity_GetUserData(pEntity); if(!EffectC_IsStringNull(R->TriggerName)) { if(GetTriggerState(R->TriggerName)) { if(R->active == GE_FALSE) { for(i=0; i<R->EffectCount; i++) R->EffectList[i] = Create(R); R->active = GE_TRUE; } } else { if(R->active == GE_TRUE) { for(i=0; i<R->EffectCount; i++) CCD->EffectManager()->Item_Delete(EFF_SPRAY, R->EffectList[i]); R->active = GE_FALSE; } } } else { if(R->active == GE_FALSE) { for(i=0; i<R->EffectCount; i++) R->EffectList[i] = Create(R); R->active = GE_TRUE; } } if(R->active == GE_TRUE) { R->origin = R->OriginOffset; if(SetOriginOffset(R->EntityName, R->BoneName, R->Model, &(R->origin))) { geVec3d_Copy(&(R->origin), &(Sp.Source)); geVec3d_AddScaled(&(Sp.Source), &(Sp.Gravity), Sp.MinUnitLife, &(Sp.Dest)); // adjust position for(i=0; i<R->EffectCount; i++) CCD->EffectManager()->Item_Modify(EFF_SPRAY, R->EffectList[i], (void *)&Sp, SPRAY_SOURCE | SPRAY_ACTUALDEST); } } } }