/* * Copyright (C) 1999 Brad Stephens * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of *the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA */ #include #include #include "../log.h" #include "../ballistics.h" #include "../terrain.h" #include "napalm.h" Shellstat_bal wepNapalmGuidance(void *info, struct Projectilepos_bal *prjpos, Shellstat_bal(*initexplosion) (struct Projectilepos_bal * prjpos, void **explosioninfo), void **explosioninfo) { int ix, iy; int i; Player_pl *plhit = NULL; unsigned char lets_blow = 0; Weapon_wep *bs; struct Projectilelist_bal *prj; double v, angle, vx1, vy1, vx2, vy2; IsectTypes_bal isect; prjpos->rox = prjpos->ox = prjpos->x; prjpos->roy = prjpos->oy = prjpos->y; prjpos->x += prjpos->vx + (bal_wind / bal_lerp_tweak); prjpos->y += prjpos->vy; prjpos->vy -= (bal_grav / bal_lerp_tweak); switch (balEnvironmentAdjustProjPos(prjpos)) { case HOLDING: /* wtf ??? */ break; case FLYING: break; case EXPLODING: lets_blow = 1; break; case FREEING: return FREEING; break; } /* Need to check five spots for terrain. ** ** <---o---> ** /|\ ** / | \ ** / | \ */ /* Left side */ isect=balCheckIntersect(prjpos->x, prjpos->y, prjpos->x-NAPALM_HEIGHT, prjpos->y, &plhit, &ix, &iy); if(isect==TERRAIN_ISECT || isect==TANK_ISECT) { lets_blow = 1; } /* lower left */ isect=balCheckIntersect(prjpos->x, prjpos->y, prjpos->x-NAPALM_HEIGHT, prjpos->y-NAPALM_HEIGHT, &plhit, &ix, &iy); if(isect==TERRAIN_ISECT || isect==TANK_ISECT) { lets_blow = 1; } /* below */ isect=balCheckIntersect(prjpos->x, prjpos->y, prjpos->x, prjpos->y-NAPALM_HEIGHT, &plhit, &ix, &iy); if(isect==TERRAIN_ISECT || isect==TANK_ISECT) { lets_blow = 1; } /* lower right */ isect=balCheckIntersect(prjpos->x, prjpos->y, prjpos->x+NAPALM_HEIGHT, prjpos->y-NAPALM_HEIGHT, &plhit, &ix, &iy); if(isect==TERRAIN_ISECT || isect==TANK_ISECT) { lets_blow = 1; } /* right side */ isect=balCheckIntersect(prjpos->x, prjpos->y, prjpos->x+NAPALM_HEIGHT, prjpos->y, &plhit, &ix, &iy); if(isect==TERRAIN_ISECT || isect==TANK_ISECT) { lets_blow = 1; } if(lets_blow == 1) { /* Only blow if vy is less than 10 or so */ if(prjpos->vy < 10) { /* Put in the napalm projectiles */ bs = wepLookupWeapon("Burning Napalm"); logPrintf(DEBUG, "Exploding Napalm with vx=%f, vy=%f\n", prjpos->vx, prjpos->vy); /* Calculate some data for determining velocities */ angle = atan(prjpos->vy / prjpos->vx); if(prjpos->vx < 0) { angle += M_PI; /* Need to get correct angle since atan goes from -90 to 90 degrees */ } v = sqrt(pow(prjpos->vx, 2) + pow(prjpos->vy, 2)); logPrintf(DEBUG, "Angle=%f, Velocity=%f\n", (angle * 180 / M_PI), v); /* Launce a projectile following the path of the original */ prj = balNewShotXY(prjpos->id, 0, prjpos->x, prjpos->y, prjpos->vx, prjpos->vy, bs); prj->stat = INITSHOT(prj); for(i = 1; i <= NAPALM_FRAGMENTS; i++) { vx1 = v * cos(angle + (NAPALM_SPREAD * i)); vy1 = v * sin(angle + (NAPALM_SPREAD * i)); vx2 = v * cos(angle - (NAPALM_SPREAD * i)); vy2 = v * sin(angle - (NAPALM_SPREAD * i)); logPrintf(DEBUG, "Shot 1: (%f,%f), Shot 2: (%f,%f)\n", vx1, vy1, vx2, vy2); prj = balNewShotXY(prjpos->id, 0, prjpos->x, prjpos->y, vx1, vy1, bs); prj->stat = INITSHOT(prj); prj = balNewShotXY(prjpos->id, 0, prjpos->x, prjpos->y, vx2, vy2, bs); prj->stat = INITSHOT(prj); } return initexplosion(prjpos, explosioninfo); } } return FLYING; } Shellstat_bal wepBurningNapalmExplosionInit(struct Projectilepos_bal * prjpos, void **explosioninfo) { struct DurationExplosion_wep *e = (struct DurationExplosion_wep*)malloc(sizeof(struct DurationExplosion_wep)); e->x = prjpos->x; e->y = prjpos->y; e->width = NAPALM_EXPL_WIDTH; e->id = prjpos->id; e->duration = NAPALM_EXPL_DURATION; e->wid = prjpos->wid; *((struct DurationExplosion_wep**)explosioninfo)=e; return EXPLODING; } Shellstat_bal wepBurningNapalmExplosion(void *info) { struct DurationExplosion_wep *prj = (struct DurationExplosion_wep *)info; Player_pl *pcur; prj->duration--; if(prj->duration < 0) { return FREEING; } else { for(pcur = pl_begin; pcur; pcur = pcur->next) { if(pcur->ready==READY && plPlayerInCircleArea(pcur, prj->x, prj->y, (prj->width/2))) { pcur->last_hit = prj->id; plDamageTank(pcur, EXPLOSIVE, prj->id, prj->wid, 1); } } return EXPLODING; } }