/*
* $Id: aero.bomb.c,v 1.1.1.1 2005/01/11 21:18:00 kstevens Exp $
*
* Author: Markus Stenberg <fingon@iki.fi>
*
* Copyright (c) 1997 Markus Stenberg
* Copyright (c) 1998-2002 Thomas Wouters
* Copyright (c) 2000-2002 Cord Awtry
* All rights reserved
*
* Created: Mon Jan 6 15:57:35 1997 fingon
* Last modified: Mon Jun 8 19:49:25 1998 fingon
*
*/
#define GMOD 1 /* Acceleration / second, in Z hexes */
#include "mech.h"
#include "aero.bomb.h"
#include "coolmenu.h"
#include "mycool.h"
#include "mech.events.h"
#include "math.h"
#include "create.h"
#include "p.mech.utils.h"
#include "p.artillery.h"
#include "p.econ_cmds.h"
BOMBINFO bombs[] = {
{"10_Inferno", 10, 1, 30}
,
{"10_Cluster", 10, 2, 30}
,
{"10_Standard", 10, 0, 130}
,
{"50_Inferno", 50, 1, 130}
,
{"50_Cluster", 50, 2, 130}
,
{"50_Standard", 50, 0, 130}
,
{"100_Inferno", 100, 1, 250}
,
{"100_Cluster", 100, 2, 250}
,
{"100_Standard", 100, 0, 250}
,
{NULL, 0, 0, 0}
};
void DestroyBomb(MECH * mech, int loc)
{
}
int BombWeight(int i)
{
return bombs[i].weight;
}
char *bomb_name(int i)
{
return bombs[i].name;
}
void bomb_list(MECH * mech, int player)
{
int bc = 0, fb;
int i, j, k;
char location[20];
static char *types[] = {
"Standard",
"Inferno",
"Cluster",
NULL
};
coolmenu *c = NULL;
addline();
cent(tprintf("Bomb payload for %s:", GetMechID(mech)));
addline();
for (i = 0; i < NUM_SECTIONS; i++) {
fb = 1;
for (j = 0; j < NUM_CRITICALS; j++)
if (IsBomb((k = GetPartType(mech, i, j)))) {
k = Bomb2I(k);
if (fb) {
ArmorStringFromIndex(i, location, MechType(mech),
MechMove(mech));
fb = 0;
}
if (!bc) {
vsi(tprintf("# %-20s %-5s %-5s %s", "Location",
"Weight", "Power", "Type"));
}
vsi(tprintf("%-2d %-20s %5d %5d", bc + 1, location,
bombs[k].weight / 10, bombs[k].aff,
types[bombs[k].type]));
bc++;
}
}
if (!bc)
cent("No bombs installed.");
addline();
ShowCoolMenu(player, c);
KillCoolMenu(c);
}
float calc_dest(MECH * mech, short *x, short *y)
{
/* Present location */
float fx = MechFX(mech);
float fy = MechFY(mech);
float fz = MechFZ(mech) / ZSCALE;
float zspd = MechStartFZ(mech) / ZSCALE;
float t, ot;
ot = t = (zspd + sqrt(zspd * zspd + 2 * GMOD * fz)) / GMOD;
t = (float) t / MOVE_TICK;
fx = fx + MechStartFX(mech) * t;
fy = fy + MechStartFY(mech) * t;
RealCoordToMapCoord(x, y, fx, fy);
return ot;
}
void bomb_aim(MECH * mech, dbref player)
{
float t; /* The time of impact */
char toi[LBUF_SIZE];
short x, y;
t = calc_dest(mech, &x, &y);
sprintf(toi, "%.1f second%s", t, (t >= 2.0 || t < 1.0) ? "" : "s");
mech_notify(mech, MECHALL,
tprintf
("Estimated bomb flight time %s, estimated landing hex %d,%d.",
toi, x, y));
}
void bomb_hit_hexes(MAP * map, int x, int y, int hitnb, int iscluster,
int aff_d, int aff_h, char *tomsg, char *otmsg, char *tomsg1,
char *otmsg1)
{
blast_hit_hexes(map, aff_d, iscluster ? 2 : 10, aff_h, x, y, tomsg,
otmsg, tomsg1, otmsg1, 0, 4, 1, 1, hitnb);
}
static void bomb_hit(bomb_shot * s)
{
switch (bombs[s->type].type) {
case 0:
HexLOSBroadcast(s->map, s->x, s->y,
"A blast rocks the area around $H!");
bomb_hit_hexes(s->map, s->x, s->y, 1, 0,
bombs[s->type].type ==
1 ? bombs[s->type].aff / 2 : bombs[s->type].aff,
bombs[s->type].type == 1 ? bombs[s->type].aff : 0,
"You receive a direct hit!", "receives a direct hit!",
"You are hit by shrapnel!", "is hit by shrapnel!");
break;
case 1:
HexLOSBroadcast(s->map, s->x, s->y,
"A fiery blast occurs in $H, spraying flaming gel everywhere!");
bomb_hit_hexes(s->map, s->x, s->y, 1, 0,
bombs[s->type].type ==
1 ? bombs[s->type].aff / 2 : bombs[s->type].aff,
bombs[s->type].type == 1 ? bombs[s->type].aff : 0,
"You receive a direct hit!", "receives a direct hit!",
"You are hit by the globs of flaming gel!",
"is hit by the globs!");
break;
case 2:
HexLOSBroadcast(s->map, s->x, s->y,
"A bomb drops rain of small bomblets in $H's surroundings!");
bomb_hit_hexes(s->map, s->x, s->y, 1, 1,
bombs[s->type].type ==
1 ? bombs[s->type].aff / 2 : bombs[s->type].aff,
bombs[s->type].type == 1 ? bombs[s->type].aff : 0,
"You are hit by ton of small munitions!",
"is hit by many small munitions!",
"You are hit by some of the small munitions!",
"is hit by some small munitions!");
break;
}
}
static void bomb_hit_event(MUXEVENT * e)
{
bomb_shot *s = (bomb_shot *) e->data;
bomb_hit(s);
free((void *) s);
}
void simulate_flight(MECH * mech, MAP * map, short *x, short *y, float t)
{
float fx = MechFX(mech);
float fy = MechFY(mech);
float fz = MechFZ(mech);
/* float fs = MechStartFZ(mech); */
float delx, dely;
float dx, dy;
int i;
short tx, ty;
if (t < 1.0)
return;
MapCoordToRealCoord(*x, *y, &dx, &dy);
delx = (dx - fx) / t;
dely = (dy - fy) / t;
for (i = 1; i < t; i++) {
fx = fx + delx;
fy = fx + dely;
fz = (float) fz - GMOD;
RealCoordToMapCoord(&tx, &ty, fx, fy);
if (tx < 0 || ty < 0 || tx >= map->map_width ||
ty >= map->map_height)
continue;
if (Elevation(map, tx, ty) > (fz / ZSCALE)) {
*x = tx;
*y = ty;
}
}
}
void bomb_drop(MECH * mech, int player, int bn)
{
int bc = 0;
int i, j, k;
int lloc = 0, lpos = 0;
float t;
short x, y;
int ob;
int di;
float dir;
bomb_shot *s;
MAP *map;
DOCHECK(bn < 0, "Negative bomb number? Gimme a break.");
bn--;
for (i = 0; i < NUM_SECTIONS; i++)
for (j = 0; j < NUM_CRITICALS; j++)
if (IsBomb((k = GetPartType(mech, i, j))) &&
!PartIsDestroyed(mech, i, j)) {
if (bc == bn) {
lloc = i;
lpos = j;
}
bc++;
}
DOCHECK(!bc, "No bombs installed.");
DOCHECK(!(map = getMap(mech->mapindex)), "You're on invalid map!");
DOCHECK(bn < 0 ||
bn >= bc, "No bomb with such number installed! (See BOMB LIST)");
MechLOSBroadcast(mech,
"detaches a small object that starts falling down..");
k = Bomb2I(GetPartType(mech, lloc, lpos));
mech_notify(mech, MECHALL, "The ship trembles as you detach a bomb..");
t = calc_dest(mech, &x, &y);
ob = (int) t / 10;
if (MadePilotSkillRoll(mech, 4 + ob) || t < 2.0)
mech_notify(mech, MECHALL,
"Despite the slight problems, you keep the craft stable enough to drop the bomb right on target..");
else {
mech_notify(mech, MECHALL,
"The ship's lurches slightly, dropping the bomb off target!");
ob = 6 * (1 + ob); /* Max distance missed */
ob = MAX(1, (Number(1, ob)) / 2);
di = Number(0, 359);
dir = di * TWOPIOVER360;
x = x + ob * cos(dir);
y = y + ob * sin(dir);
}
simulate_flight(mech, map, &x, &y, t);
if (x < 0 || y < 0 || x >= map->map_width || y >= map->map_height)
return;
SetPartType(mech, lloc, lpos, 0);
Create(s, bomb_shot, 1);
s->x = x;
s->y = y;
s->type = k;
s->map = map;
SetCargoWeight(mech);
muxevent_add(MAX(1, t), 0, EVENT_DHIT, bomb_hit_event, (void *) s, NULL);
}
void mech_bomb(dbref player, void *data, char *buffer)
{
MECH *mech = (MECH *) data;
char *args[3];
int argc;
int bn;
cch(MECH_USUALSO);
DOCHECK(!(argc =
mech_parseattributes(buffer, args, 3)),
"(At least) one option required.");
DOCHECK(argc > 2, "Too many arguments!");
if (!strcasecmp(args[0], "list")) {
bomb_list(mech, player);
return;
}
DOCHECK(Landed(mech), "The craft is landed!");
if (!strcasecmp(args[0], "aim")) {
bomb_aim(mech, player);
return;
}
DOCHECK(strcasecmp(args[0], "drop"), "Invalid argument to BOMB!");
DOCHECK(argc < 2,
"The BOMB commands needs to know WHICH bomb to drop!");
DOCHECK(Readnum(bn, args[1]), "Invalid bomb number!");
bomb_drop(mech, player, bn);
}