#include "Weapons.h" #include "WorldManager.h" #include "ObjectWrapper.h" #include #include "SoundManager.h" void InitWeapon(VWeapon * w, int type, Boolean doubleMaxDistance) { w->Type = type; w->InitialPos.x = 0.0; w->InitialPos.y = 0.0; w->InitialPos.z = 0.0; w->Target = w->InitialPos; w->taggedForRemoval = 0; w->next = NULL; w->Trail = NULL; InitObject(&w->Object); switch (type) { case WEAPONTYPEBULLET: BuildBulletModel(&w->Object.Model); w->Damage = 1; w->Speed = BULLETSPEED; if (doubleMaxDistance) w->MaxDistance = ((MAXBULLETDISTANCE * 2) * (MAXBULLETDISTANCE * 2)); else w->MaxDistance = (MAXBULLETDISTANCE * MAXBULLETDISTANCE); break; case WEAPONTYPEROCKET: BuildRocketModel(&w->Object.Model); w->Damage = 10; w->Speed = ROCKETSPEED; w->MaxDistance = (MAXROCKETDISTANCE * MAXROCKETDISTANCE); break; } CalculateRadius(&w->Object); } void CleanUpWeapon(VWeapon * w) { CleanUpObject(&w->Object); CleanUpTrail(w->Trail); } void StartWeapon(VWeapon * w, Vector * startPos, float speedAdjustment, Vector * forward, Vector * up) { w->InitialPos = *startPos; w->Object.Position = *startPos; w->Object.Front = *forward; w->Object.Up = *up; w->Speed += speedAdjustment; CrossProduct(&w->Object.Up, &w->Object.Front, &w->Object.Right); NormalizeVector(&w->Object.Right); /* Start at the near clipping plane */ w->Object.Position.x += (w->Object.Front.x * 1.5); w->Object.Position.y += (w->Object.Front.y * 1.5); w->Object.Position.z += (w->Object.Front.z * 1.5); } void RunWeapon(VWeapon * w, float interval, void * TheWorld) { VWorld * world; VObject * Object; VObjectWrapper * ObjectList; Vector Start; Vector End; Vector wall; world = (VWorld *) TheWorld; ObjectList = world->Objects; w->Target = w->Object.Front; if (w->Type == WEAPONTYPEROCKET) { for (; ObjectList != NULL; ObjectList = ObjectList->next) { if(!ObjectList->target) continue; WObjectObject(ObjectList, &Object); if (Object != NULL) w->Target = Object->Position; break; } } ObjectList = world->Objects; switch (w->Type) { case WEAPONTYPEBULLET: break; case WEAPONTYPEROCKET: Start = w->Object.Position; if (w->Target.x != w->Object.Front.x && w->Target.y != w->Object.Front.y && w->Target.z != w->Object.Front.z) { Vector intendedAngle; SubtractVector(&w->Target, &w->Object.Position, &intendedAngle); NormalizeVector(&intendedAngle); intendedAngle.x *= (ROCKETROTATERATE / interval); intendedAngle.y *= (ROCKETROTATERATE / interval); intendedAngle.z *= (ROCKETROTATERATE / interval); w->Object.Front.x += intendedAngle.x; w->Object.Front.y += intendedAngle.y; w->Object.Front.z += intendedAngle.z; NormalizeVector(&w->Object.Front); CrossProduct(&w->Object.Front, &w->Object.Right, &w->Object.Up); CrossProduct(&w->Object.Up, &w->Object.Front, &w->Object.Right); NormalizeVector(&w->Object.Right); NormalizeVector(&w->Object.Up); } w->Speed += ROCKETACCELERATION; if (w->Speed > MAXROCKETSPEED) w->Speed = MAXROCKETSPEED; break; } w->Object.Position.x += ((w->Object.Front.x / interval) * w->Speed); w->Object.Position.y += ((w->Object.Front.y / interval) * w->Speed); w->Object.Position.z += ((w->Object.Front.z / interval) * w->Speed); for (; ObjectList != NULL; ObjectList = ObjectList->next) { if (ObjectList->Type != VENEMY && ObjectList->Type != VOBJECT) continue; WObjectObject(ObjectList, &Object); if (Object != NULL && fabs(((w->Object.Position.x - Object->Position.x) * (w->Object.Position.x - Object->Position.x)) + ((w->Object.Position.y - Object->Position.y) * (w->Object.Position.y - Object->Position.y)) + ((w->Object.Position.z - Object->Position.z) * (w->Object.Position.z - Object->Position.z))) <= (w->Object.Radius + Object->Radius)) { if(ObjectList->Type == VENEMY) { PlaySound(GetSoundManager(), ENEMYHITSOUND); HitEnemy(ObjectList->e, w->Damage); if(ObjectList->e->Shields <= 0) { ObjectList->taggedForRemoval = true; ObjectList->exploded = 1; ObjectList->explosionLevel = 7; } else { ObjectList->exploded = 2; ObjectList->explosionLevel = 1; } } else { PlaySound(GetSoundManager(), IMPACTSOUND); ObjectList->o->Durability -= w->Damage; if (ObjectList->o->Durability <= 0) { ObjectList->taggedForRemoval = true; ObjectList->exploded = 1; } else { ObjectList->exploded = 2; } } w->taggedForRemoval = 2; break; } } if ((((w->Object.Position.x - w->InitialPos.x) * (w->Object.Position.x - w->InitialPos.x)) + ((w->Object.Position.y - w->InitialPos.y) * (w->Object.Position.y - w->InitialPos.y)) + ((w->Object.Position.z - w->InitialPos.z) * (w->Object.Position.z - w->InitialPos.z))) > w->MaxDistance) { w->taggedForRemoval = 2; } if (!w->taggedForRemoval) { if (fabs(((w->Object.Position.x - world->Camera.Position.x) * (w->Object.Position.x - world->Camera.Position.x)) + ((w->Object.Position.y - world->Camera.Position.y) * (w->Object.Position.y - world->Camera.Position.y)) + ((w->Object.Position.z - world->Camera.Position.z) * (w->Object.Position.z - world->Camera.Position.z))) <= (w->Object.Radius + PLAYERSHIPRADIUS) && world->Player.Shields > 0) { PlaySound(GetSoundManager(), PLAYERHITSOUND); DamagePlayer(world, w->Damage); w->taggedForRemoval = 2; } } if(w->Type == WEAPONTYPEROCKET) { End = w->Object.Position; if(w->Trail) { if(w->Trail->TimeLeft < w->Trail->duration - 0.15) NewTrail(&w->Trail, &Start); } else NewTrail(&w->Trail, &Start); RunTrail(w->Trail, interval); } if(!InBounds(world, &w->Object.Position, sqrt(w->Object.Radius), &wall)) { w->Object.Position.x -= ((w->Object.Front.x / interval) * w->Speed * 3); w->Object.Position.y -= ((w->Object.Front.y / interval) * w->Speed * 3); w->Object.Position.z -= ((w->Object.Front.z / interval) * w->Speed * 3); w->taggedForRemoval = 2; } } void DrawWeapon(VWeapon * w) { DrawObject(&w->Object); DrawTrail(w->Trail); } void CopyWeapon(VWeapon * src, VWeapon * dest) { BlockMove(src, dest, sizeof(VWeapon)); dest->next = NULL; dest->Trail = NULL; } void NewTrail(VTrail ** t, Vector * Start) { VTrail * theTrail; theTrail = (VTrail *) NewPtr(sizeof(VTrail)); InitObject(&theTrail->Object); BuildTrailModel(&theTrail->Object.Model); theTrail->Object.Position = *Start; theTrail->duration = 3; theTrail->TimeLeft = 3; theTrail->previous = NULL; theTrail->next = *t; theTrail->Direction.x = ((float)(Random() % 40)) / 10000; theTrail->Direction.y = ((float)(Random() % 40)) / 10000; theTrail->Direction.z = ((float)(Random() % 40)) / 10000; switch (abs(Random() % 3)) { case 0: theTrail->Object.Model.Color[1] = 0.4; break; case 1: theTrail->Object.Model.Color[1] = 0.6; break; case 2: theTrail->Object.Model.Color[1] = 0.8; break; } if(*t) (*t)->previous = theTrail; *t = theTrail; } void DrawTrail(VTrail * t) { VTrail * theTrail; theTrail = t; while(theTrail != NULL) { DrawObject(&theTrail->Object); theTrail = theTrail->next; } } void RunTrail(VTrail * t, float interval) { VTrail * theTrail; VTrail * tempTrail; theTrail = t; while(theTrail != NULL) { theTrail->TimeLeft -= interval; if(theTrail->TimeLeft < 0) { tempTrail = theTrail->next; RemoveTrail(&theTrail); theTrail = tempTrail; continue; } AddVector(&theTrail->Object.Position, &theTrail->Direction, &theTrail->Object.Position); theTrail->Object.Model.Color[3] -= 1 / (theTrail->duration / interval); theTrail = theTrail->next; } } void CleanUpTrail(VTrail * t) { VTrail * theTrail; VTrail * tempTrail; theTrail = t; while(theTrail != NULL) { tempTrail = theTrail; theTrail = theTrail->next; CleanUpObject(&tempTrail->Object); DisposePtr((Ptr)tempTrail); } } void RemoveTrail(VTrail ** trail) { VTrail * t; t = *trail; if(t->previous) t->previous->next = t->next; if(t->next) t->next->previous = t->previous; *trail = NULL; CleanUpObject(&t->Object); DisposePtr((Ptr)t); }