src/hcode/btech/mech.ammodump.c

Go to the documentation of this file.
00001 /*
00002  * Author: Cord Awtry <kipsta@mediaone.net>
00003  * Author: Cord Awtry <kipsta@mediaone.net>
00004  *  Copyright (c) 2000-2002 Cord Awtry
00005  *       All rights reserved
00006  *
00007  * Based on work that was:
00008  *  Copyright (c) 1997 Markus Stenberg
00009  *  Copyright (c) 1998-2000 Thomas Wouters
00010  */
00011 
00012 #include "mech.h"
00013 #include "mech.events.h"
00014 #include "p.mech.ammodump.h"
00015 #include "p.mech.build.h"
00016 #include "p.mech.combat.misc.h"
00017 #include "p.mech.damage.h"
00018 #include "p.mech.partnames.h"
00019 #include "p.mech.utils.h"
00020 
00021 static void mech_dump_event(MUXEVENT * ev)
00022 {
00023         MECH *mech = (MECH *) ev->data;
00024         int arg = (int) ev->data2;
00025         int loc;
00026         int i, l;
00027         int d, e = 0;
00028         char buf[SBUF_SIZE];
00029         int weapindx;
00030 
00031         if(!Started(mech))
00032                 return;
00033         i = MechType(mech) == CLASS_MECH ? 7 : 5;
00034         /* Global ammo droppage */
00035         if(!arg) {
00036                 for(; i >= 0; i--)
00037                         for(l = CritsInLoc(mech, i) - 1; l >= 0; l--)
00038                                 if(IsAmmo(GetPartType(mech, i, l)))
00039                                         if(GetPartData(mech, i, l))
00040                                                 Dump_Decrease(mech, i, l, &e);
00041                 if(e > 1)
00042                         MECHEVENT(mech, EVENT_DUMP, mech_dump_event, DUMP_GRAD_TICK, arg);
00043                 else {
00044                         mech_notify(mech, MECHALL, "All ammunition dumped.");
00045                         MechLOSBroadcast(mech,
00046                                                          "no longer has ammo dumping from hatches on its back.");
00047                 }
00048                 return;
00049         }
00050         if(arg < 256) {
00051                 loc = arg - 1;
00052                 l = CritsInLoc(mech, loc);
00053                 for(i = 0; i < l; i++)
00054                         if(IsAmmo(GetPartType(mech, loc, i)))
00055                                 if(!PartIsNonfunctional(mech, loc, i))
00056                                         if((d = GetPartData(mech, loc, i)))
00057                                                 Dump_Decrease(mech, loc, i, &e);
00058                 if(e > 1)
00059                         MECHEVENT(mech, EVENT_DUMP, mech_dump_event, DUMP_GRAD_TICK, arg);
00060                 else if(e == 1 && Started(mech)) {
00061                         ArmorStringFromIndex(loc, buf, MechType(mech), MechMove(mech));
00062                         mech_printf(mech, MECHALL, "All ammunition in %s dumped.", buf);
00063                         MechLOSBroadcast(mech,
00064                                                          "no longer has ammo dumping from hatches on its back.");
00065                 }
00066                 return;
00067         }
00068         if(arg < 65536) {
00069                 weapindx = (arg / 256) - 1;
00070                 for(; i >= 0; i--)
00071                         for(l = CritsInLoc(mech, i) - 1; l >= 0; l--)
00072                                 if(IsAmmo(GetPartType(mech, i, l)))
00073                                         if(Ammo2WeaponI(GetPartType(mech, i, l)) == weapindx)
00074                                                 if(GetPartData(mech, i, l))
00075                                                         Dump_Decrease(mech, i, l, &e);
00076                 if(e > 1)
00077                         MECHEVENT(mech, EVENT_DUMP, mech_dump_event, DUMP_GRAD_TICK, arg);
00078                 else {
00079                         mech_printf(mech, MECHALL, "Ammunition for %s dumped!",
00080                                                 get_parts_long_name(I2Weapon(weapindx), 0));
00081                         MechLOSBroadcast(mech,
00082                                                          "no longer has ammo dumping from hatches on its back.");
00083                 }
00084                 return;
00085         }
00086         l = ((arg >> 16) & 0xFF) - 1;
00087         i = ((arg >> 24) & 0xFF) - 1;
00088         e = 0;
00089         if(GetPartData(mech, l, i))
00090                 Dump_Decrease(mech, l, i, &e);
00091         if(e > 1) {
00092                 MECHEVENT(mech, EVENT_DUMP, mech_dump_event, DUMP_GRAD_TICK, arg);
00093         } else {
00094                 ArmorStringFromIndex(l, buf, MechType(mech), MechMove(mech));
00095                 mech_printf(mech, MECHALL,
00096                                         "Ammunition in %s crit %i dumped!", buf, i + 1);
00097                 MechLOSBroadcast(mech,
00098                                                  "no longer has ammo dumping from hatches on its back.");
00099         }
00100 }
00101 
00102 void mech_dump(dbref player, void *data, char *buffer)
00103 {
00104         MECH *mech = (MECH *) data;
00105         int argc;
00106         char *args[2];
00107         int weapnum;
00108         int weapindx;
00109         int section;
00110         int critical;
00111         int ammoLoc;
00112         int ammoCrit;
00113         int loc;
00114         int i, l, count = 0, d;
00115         char buf[MBUF_SIZE];
00116         int type = 0;
00117 
00118         cch(MECH_USUAL);
00119         argc = mech_parseattributes(buffer, args, 2);
00120         DOCHECK(argc < 1, "Not enough arguments to the function");
00121         weapnum = atoi(args[0]);
00122 
00123         DOCHECKMA(Jumping(mech), "You can't dump ammo while jumping!");
00124         DOCHECKMA(IsRunning(MechDesiredSpeed(mech), MMaxSpeed(mech)),
00125                           "You can't dump ammo while running!");
00126 
00127         if(!strcasecmp(args[0], "stop")) {
00128                 DOCHECKMA(!Dumping(mech), "You aren't dumping anything!");
00129                 mech_notify(mech, MECHALL, "Ammo dumping halted.");
00130                 StopDump(mech);
00131                 MechLOSBroadcast(mech,
00132                                                  "no longer has ammo dumping from hatches on its back.");
00133                 return;
00134         } else if(!strcasecmp(args[0], "all")) {
00135                 count = 0;
00136                 i = MechType(mech) == CLASS_MECH ? 7 : 5;
00137                 for(; i >= 0; i--)
00138                         for(l = CritsInLoc(mech, i) - 1; l >= 0; l--)
00139                                 if(IsAmmo(GetPartType(mech, i, l)))
00140                                         if(GetPartData(mech, i, l))
00141                                                 count++;
00142                 DOCHECKMA(!count, "You have no ammo to dump!");
00143                 DOCHECKMA(Dumping_Type(mech, 0), "You're already dumping your ammo!");
00144                 StopDump(mech);
00145                 mech_notify(mech, MECHALL, "Starting dumping of all ammunition..");
00146                 MechLOSBroadcast(mech,
00147                                                  "starts dumping ammo from hatches on its back.");
00148                 MECHEVENT(mech, EVENT_DUMP, mech_dump_event, DUMP_GRAD_TICK, 0);
00149                 return;
00150         } else if(!weapnum && strcmp(args[0], "0")) {
00151                 /* Try to find hitloc instead */
00152                 DOCHECKMA(Dumping(mech), "You're already dumping some ammo!");
00153                 loc = ArmorSectionFromString(MechType(mech), MechMove(mech), args[0]);
00154                 DOCHECK(loc < 0, "Invalid location or weapon number!");
00155                 ArmorStringFromIndex(loc, buf, MechType(mech), MechMove(mech));
00156                 if(args[1]) {
00157                         i = atoi(args[1]);
00158                         i--;
00159                         if(i >= 0 && i < 12) {
00160                                 if(IsAmmo(GetPartType(mech, loc, i)))
00161                                         if(!PartIsNonfunctional(mech, loc, i))
00162                                                 if((d = GetPartData(mech, loc, i)))
00163                                                         count++;
00164                                 DOCHECKMA(!count,
00165                                                   tprintf("There is no ammunition in %s crit %i!",
00166                                                                   buf, i + 1));
00167                                 type = (((i + 1) << 8) | (loc + 1));
00168                                 DOCHECKMA(type & ~0xFFFF,
00169                                                   "Internal inconsistency, dump failed!");
00170                                 type = type << 16;
00171                                 mech_printf(mech, MECHALL,
00172                                                         "Starting dumping of ammunition in %s crit %i..",
00173                                                         buf, i + 1);
00174                                 MechLOSBroadcast(mech,
00175                                                                  "starts dumping ammo from hatches on its back.");
00176                                 MECHEVENT(mech, EVENT_DUMP, mech_dump_event,
00177                                                   DUMP_GRAD_TICK, type);
00178                                 return;
00179                         }
00180                 }
00181                 l = CritsInLoc(mech, loc);
00182                 for(i = 0; i < l; i++)
00183                         if(IsAmmo(GetPartType(mech, loc, i)))
00184                                 if(!PartIsNonfunctional(mech, loc, i))
00185                                         if((d = GetPartData(mech, loc, i)))
00186                                                 count++;
00187                 DOCHECKMA(!count, tprintf("There is no ammunition in %s!", buf));
00188                 type = loc + 1;
00189                 mech_printf(mech, MECHALL,
00190                                         "Starting dumping of ammunition in %s..", buf);
00191                 MechLOSBroadcast(mech,
00192                                                  "starts dumping ammo from hatches on its back.");
00193                 MECHEVENT(mech, EVENT_DUMP, mech_dump_event, DUMP_GRAD_TICK, type);
00194                 return;
00195         }
00196         weapindx = FindWeaponIndex(mech, weapnum);
00197         if(weapnum < 0)
00198                 SendError(tprintf
00199                                   ("CHEATER: #%d tried to crash mux with command 'dump %d'!",
00200                                    (int) player, weapnum));
00201         DOCHECKMA(Dumping(mech), "You're already dumping some ammo!");
00202         DOCHECK(weapindx < 0, "Invalid weapon number!");
00203         FindWeaponNumberOnMech(mech, weapnum, &section, &critical);
00204         DOCHECK(MechWeapons[weapindx].type == TBEAM ||
00205                         MechWeapons[weapindx].type == THAND,
00206                         "That weapon doesn't use ammunition!");
00207         DOCHECK(!FindAmmoForWeapon_sub(mech, -1, -1, weapindx, 0, &ammoLoc,
00208                                                                    &ammoCrit, 0, 0),
00209                         "You don't have any ammunition for that weapon stored on this mech!");
00210         DOCHECK(GetPartData(mech, ammoLoc, ammoCrit) == 0,
00211                         "You are out of ammunition for that weapon already!");
00212         type = 256 * (weapindx + 1);
00213         mech_printf(mech, MECHALL, "Starting dumping %s ammunition..",
00214                                 get_parts_long_name(I2Weapon(weapindx), 0));
00215         MechLOSBroadcast(mech, "starts dumping ammo from hatches on its back.");
00216         MECHEVENT(mech, EVENT_DUMP, mech_dump_event, DUMP_GRAD_TICK, type);
00217 #if 0
00218         while (FindAmmoForWeapon(mech, weapindx, 0, &ammoLoc, &ammoCrit))
00219                 GetPartData(mech, ammoLoc, ammoCrit) = 0;
00220         mech_printf(mech, MECHALL, "Ammunition for %s dumped!",
00221                                 get_parts_long_name(I2Weapon(weapindx), 0));
00222 #endif
00223 }
00224 
00225 int Dump_Decrease(MECH * mech, int loc, int pos, int *hm)
00226 {
00227         int c, index, weapindx, rem;
00228 
00229 #define RUP(a) { if (*hm < a) *hm = a; return a; }
00230         /* It _is_ ammo, and contains something */
00231 
00232         if(IsAmmo((index = GetPartType(mech, loc, pos))))
00233                 if(!PartIsNonfunctional(mech, loc, pos))
00234                         if((c = GetPartData(mech, loc, pos))) {
00235                                 weapindx = Ammo2WeaponI(index);
00236                                 if(MechWeapons[weapindx].ammoperton < DUMP_SPEED) {
00237                                         if((muxevent_tick % (DUMP_SPEED /
00238                                                                                  MechWeapons[weapindx].ammoperton)))
00239                                                 RUP(2);
00240                                         /* fine, we remove 1 */
00241                                         rem = 1;
00242                                 } else
00243                                         rem =
00244                                                 MIN(c, MechWeapons[weapindx].ammoperton / DUMP_SPEED);
00245                                 ammo_expedinture_check(mech, weapindx, rem - 1);
00246                                 SetPartData(mech, loc, pos, c - rem);
00247                                 if(c <= rem)
00248                                         RUP(1);
00249                                 RUP(2);
00250                         }
00251         return 0;
00252 }
00253 
00254 /*
00255  * The function is for blowing up some of the ammo that's being dumped from
00256  * a mech when it takes a rear torso shot.
00257  *
00258  * FASA rules state that if a mech takes a rear torso shot while dumping ammo,
00259  * all the dumping ammo explodes and goes to the armor of that location. That's
00260  * a bit harsh in RS as getting behind someone ain't that hard. So what we do is
00261  * if you're dumping ammo and take a rear torso shot, we, on a roll of 7 or less, 
00262  * call this BlowDumpingAmmo function. This function finds all the ammo you're dumping
00263  * and blows up ONE ROUND of one type, randomly. If you're dumping a lot and get hit
00264  * a few times (like from an LRM) you could get a bunch of little booms which
00265  * could really ruin your day.
00266  */
00267 
00268 void BlowDumpingAmmo(MECH * mech, MECH * attacker, int wHitLoc)
00269 {
00270         struct objDumpingAmmo aobjAmmoItems[MAX_WEAPONS_PER_MECH];
00271         int wEventData = -1;
00272         int wSecIter, wSlotIter;
00273         int wcAmmoItems = 0;
00274         int wPartType = 0, wPartData = 0;
00275         int wLoc = 0;
00276         int wWeapIdx = 0;
00277         int wRndIdx = 0;
00278         int wBlowDamage = 0;
00279 
00280         DumpingData(mech, &wEventData);
00281         if(wEventData < 0)
00282                 return;
00283         if(!wEventData) {                       /* Global ammo dump */
00284                 for(wSecIter = 7; wSecIter >= 0; wSecIter--)
00285                         for(wSlotIter = CritsInLoc(mech, wSecIter) - 1;
00286                                 wSlotIter >= 0; wSlotIter--) {
00287                                 wPartType = GetPartType(mech, wSecIter, wSlotIter);
00288                                 if(IsAmmo(wPartType))
00289                                         if(GetPartData(mech, wSecIter, wSlotIter)) {
00290                                                 aobjAmmoItems[wcAmmoItems].wDamage =
00291                                                         FindMaxAmmoDamage(Ammo2WeaponI(wPartType));
00292                                                 aobjAmmoItems[wcAmmoItems].wLocation = wSecIter;
00293                                                 aobjAmmoItems[wcAmmoItems].wSlot = wSlotIter;
00294                                                 aobjAmmoItems[wcAmmoItems].wWeapIdx =
00295                                                         Ammo2WeaponI(wPartType);
00296                                                 aobjAmmoItems[wcAmmoItems].wPartType = wPartType;
00297                                                 wcAmmoItems++;
00298                                         }
00299                         }
00300         } else if(wEventData < 256) {   /* Location specific ammo dump */
00301                 wLoc = wEventData - 1;
00302                 for(wSlotIter = 0; wSlotIter < CritsInLoc(mech, wLoc); wSlotIter++) {
00303                         wPartType = GetPartType(mech, wLoc, wSlotIter);
00304 
00305 /*     wPartType = GetPartType(mech, wSecIter, wSlotIter); */
00306                         if(IsAmmo(wPartType))
00307                                 if(!PartIsNonfunctional(mech, wLoc, wSlotIter) &&
00308                                    GetPartData(mech, wLoc, wSlotIter)) {
00309                                         aobjAmmoItems[wcAmmoItems].wDamage =
00310                                                 FindMaxAmmoDamage(Ammo2WeaponI(wPartType));
00311                                         aobjAmmoItems[wcAmmoItems].wLocation = wLoc;
00312                                         aobjAmmoItems[wcAmmoItems].wSlot = wSlotIter;
00313                                         aobjAmmoItems[wcAmmoItems].wWeapIdx =
00314                                                 Ammo2WeaponI(wPartType);
00315                                         aobjAmmoItems[wcAmmoItems].wPartType = wPartType;
00316                                         wcAmmoItems++;
00317                                 }
00318                 }
00319         } else if(wEventData < 65536) { /* Weapon specific ammo dump */
00320                 wWeapIdx = (wEventData / 256) - 1;
00321                 for(wSecIter = 7; wSecIter >= 0; wSecIter--)
00322                         for(wSlotIter = CritsInLoc(mech, wSecIter) - 1;
00323                                 wSlotIter >= 0; wSlotIter--) {
00324                                 wPartType = GetPartType(mech, wSecIter, wSlotIter);
00325                                 if(IsAmmo(wPartType) && (Ammo2WeaponI(wPartType) == wWeapIdx)) {
00326                                         aobjAmmoItems[wcAmmoItems].wDamage =
00327                                                 FindMaxAmmoDamage(Ammo2WeaponI(wPartType));
00328                                         aobjAmmoItems[wcAmmoItems].wLocation = wSecIter;
00329                                         aobjAmmoItems[wcAmmoItems].wSlot = wSlotIter;
00330                                         aobjAmmoItems[wcAmmoItems].wWeapIdx =
00331                                                 Ammo2WeaponI(wPartType);
00332                                         aobjAmmoItems[wcAmmoItems].wPartType = wPartType;
00333                                         wcAmmoItems++;
00334                                 }
00335                         }
00336         } else {                                        /* crit specific dump */
00337                 wSecIter = ((wEventData >> 16) & 0xFF) - 1;
00338                 wSlotIter = ((wEventData >> 24) & 0xFF) - 1;
00339                 wPartType = GetPartType(mech, wSecIter, wSlotIter);
00340                 aobjAmmoItems[wcAmmoItems].wDamage =
00341                         FindMaxAmmoDamage(Ammo2WeaponI(wPartType));
00342                 aobjAmmoItems[wcAmmoItems].wLocation = wSecIter;
00343                 aobjAmmoItems[wcAmmoItems].wSlot = wSlotIter;
00344                 aobjAmmoItems[wcAmmoItems].wWeapIdx = Ammo2WeaponI(wPartType);
00345                 aobjAmmoItems[wcAmmoItems].wPartType = wPartType;
00346                 wcAmmoItems++;
00347         }
00348 
00349         if(wcAmmoItems > 0) {
00350                 wRndIdx = Number(0, wcAmmoItems - 1);
00351                 wBlowDamage = aobjAmmoItems[wRndIdx].wDamage;
00352                 wSecIter = aobjAmmoItems[wRndIdx].wLocation;
00353                 wSlotIter = aobjAmmoItems[wRndIdx].wSlot;
00354                 wWeapIdx = aobjAmmoItems[wRndIdx].wWeapIdx;
00355                 if(wBlowDamage > 0) {
00356                         MechLOSBroadcast(mech,
00357                                                          "'s rear armor lights up as ammo being dumped ignites!");
00358                         mech_printf(mech, MECHALL,
00359                                                 "%%ch%%crSome of the %s ammo dumping out of your mech ignites!%%cn",
00360                                                 get_parts_long_name(I2Weapon(wWeapIdx), 0));
00361                         DamageMech(mech, attacker, 0, -1, wHitLoc, 1, 0,
00362                                            wBlowDamage, -1, -1, 0, -1, 0, 1);
00363                         /*
00364                          * Decrement the ammo one round
00365                          */
00366                         wPartData = GetPartData(mech, wSecIter, wSlotIter);
00367                         if(wPartData > 0)
00368                                 SetPartData(mech, wSecIter, wSlotIter, wPartData - 1);
00369                         mech_notify(mech, MECHALL,
00370                                                 "%ch%crAll ammo dumping operations have stopped!%cn");
00371                         StopDump(mech);
00372                 }
00373         }
00374 }
00375 
00376 int FindMaxAmmoDamage(int wWeapIdx)
00377 {
00378         int wDamage = MechWeapons[wWeapIdx].damage;
00379         int wIter = 0;
00380 
00381         if(IsMissile(wWeapIdx) || IsArtillery(wWeapIdx)) {
00382                 for(wIter = 0; MissileHitTable[wIter].key != -1; wIter++)
00383                         if(MissileHitTable[wIter].key == wWeapIdx)
00384                                 wDamage *= MissileHitTable[wIter].num_missiles[10];
00385         }
00386 
00387         return wDamage;
00388 }

Generated on Mon May 28 04:25:21 2007 for BattletechMUX by  doxygen 1.4.7