00001
00002
00003
00004
00005
00006
00007
00008
00009
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
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
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, §ion, &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
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
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
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
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) {
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) {
00301 wLoc = wEventData - 1;
00302 for(wSlotIter = 0; wSlotIter < CritsInLoc(mech, wLoc); wSlotIter++) {
00303 wPartType = GetPartType(mech, wLoc, wSlotIter);
00304
00305
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) {
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 {
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
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 }