00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "config.h"
00012
00013 #include <stdio.h>
00014 #include <stdlib.h>
00015 #include <math.h>
00016 #include <sys/file.h>
00017
00018 #include "mech.h"
00019 #include "map.h"
00020 #include "mech.events.h"
00021 #include "p.mech.restrict.h"
00022 #include "p.mech.consistency.h"
00023 #include "p.mech.utils.h"
00024 #include "p.mech.startup.h"
00025 #include "p.ds.bay.h"
00026 #include "p.btechstats.h"
00027 #include "p.mechrep.h"
00028 #include "p.crit.h"
00029 #include "p.mech.combat.h"
00030 #include "p.mech.damage.h"
00031 #include "p.template.h"
00032 #include "p.bsuit.h"
00033 #include "p.mech.los.h"
00034 #include "p.aero.bomb.h"
00035 #include "autopilot.h"
00036
00037 #ifdef BT_ADVANCED_ECON
00038 #include "p.mech.tech.do.h"
00039 #endif
00040
00041 #ifdef BT_PART_WEIGHTS
00042
00043 extern int internalsweight[];
00044 extern int cargoweight[];
00045 #endif
00046
00047 #ifdef BT_MOVEMENT_MODES
00048 #include "failures.h"
00049 #endif
00050
00051
00052 #define DEG2RAD(d) ((float)(d) * (3.14159265f / 180.f))
00053 #define RAD2DEG(d) ((float)(d) * (180.f / 3.14159265f))
00054
00055 extern dbref pilot_override;
00056
00057 char *mechtypenames[CLASS_LAST + 1] = {
00058 "mech", "tank", "VTOL", "vessel", "aerofighter", "DropShip"
00059 };
00060
00061 const char *mechtypename(MECH * foo)
00062 {
00063 return mechtypenames[(int) MechType(foo)];
00064 }
00065
00066 int MNumber(MECH * mech, int low, int high)
00067 {
00068 if((muxevent_tick / RANDOM_TICK) != MechLastRndU(mech)) {
00069 MechRnd(mech) = random();
00070 MechLastRndU(mech) = muxevent_tick / RANDOM_TICK;
00071 }
00072 return (low + MechRnd(mech) % (high - low + 1));
00073 }
00074
00075 char *MechIDS(MECH * mech, int islower)
00076 {
00077 static char buf[3];
00078
00079 if(mech) {
00080 buf[0] = MechID(mech)[0];
00081 buf[1] = MechID(mech)[1];
00082 } else {
00083 buf[0] = '*';
00084 buf[1] = '*';
00085 }
00086 buf[2] = 0;
00087
00088 if(islower) {
00089 buf[0] = tolower(buf[0]);
00090 buf[1] = tolower(buf[1]);
00091 }
00092 return buf;
00093 }
00094
00095 char *MyToUpper(char *string)
00096 {
00097 if(*string)
00098 *string = toupper(*string);
00099 return string;
00100 }
00101
00102 int CritsInLoc(MECH * mech, int index)
00103 {
00104 if(MechType(mech) == CLASS_MECH)
00105 switch (index) {
00106 case HEAD:
00107 case RLEG:
00108 case LLEG:
00109 return 6;
00110 case RARM:
00111 case LARM:
00112 if(MechIsQuad(mech))
00113 return 6;
00114 } else if(MechType(mech) == CLASS_MW)
00115 return 2;
00116 return NUM_CRITICALS;
00117 }
00118
00119 int SectHasBusyWeap(MECH * mech, int sect)
00120 {
00121 int i = 0, count, critical[MAX_WEAPS_SECTION];
00122 unsigned char weaptype[MAX_WEAPS_SECTION];
00123 unsigned char weapdata[MAX_WEAPS_SECTION];
00124
00125 count = FindWeapons(mech, sect, weaptype, weapdata, critical);
00126 for(i = 0; i < count; i++)
00127 if(WpnIsRecycling(mech, sect, critical[i]))
00128 return 1;
00129 return 0;
00130 }
00131
00132 MAP *ValidMap(dbref player, dbref map)
00133 {
00134 char *str;
00135 MAP *maps;
00136
00137 DOCHECKN(!Good_obj(map), "Index out of range!");
00138 str = silly_atr_get(map, A_XTYPE);
00139 DOCHECKN(!str || !*str, "That is not a valid map! (no XTYPE!)");
00140 DOCHECKN(strcmp("MAP", str), "That is not a valid map!");
00141 DOCHECKN(!(maps = getMap(map)), "The map has not been allocated!!");
00142 return maps;
00143 }
00144
00145 dbref FindMechOnMap(MAP * map, char *mechid)
00146 {
00147 int loop;
00148 MECH *tempMech;
00149
00150 for(loop = 0; loop < map->first_free; loop++)
00151 if(map->mechsOnMap[loop] != -1) {
00152 tempMech = getMech(map->mechsOnMap[loop]);
00153 if(tempMech && !strncasecmp(MechID(tempMech), mechid, 2))
00154 return tempMech->mynum;
00155 }
00156 return -1;
00157 }
00158
00159 dbref FindTargetDBREFFromMapNumber(MECH * mech, char *mapnum)
00160 {
00161 MAP *map;
00162
00163 if(mech->mapindex == -1)
00164 return -1;
00165 map = getMap(mech->mapindex);
00166 if(!map) {
00167 SendError(tprintf("FTDBREFFMN:invalid map:Mech: %d Index: %d",
00168 mech->mynum, mech->mapindex));
00169 mech->mapindex = -1;
00170 return -1;
00171 }
00172 return FindMechOnMap(map, mapnum);
00173 }
00174
00175 void FindComponents(float magnitude, int degrees, float *x, float *y)
00176 {
00177 *x = magnitude * fcos((float) (TWOPIOVER360 * (degrees + 90)));
00178 *y = magnitude * fsin((float) (TWOPIOVER360 * (degrees + 90)));
00179 *x = -(*x);
00180 *y = -(*y);
00181 }
00182
00183 static int Leave_Hangar(MAP * map, MECH * mech)
00184 {
00185 MECH *car = NULL;
00186 int mapob;
00187 mapobj *mapo;
00188
00189
00190
00191 mapob = mech->mapindex;
00192 if(MechCarrying(mech) > 0)
00193 car = getMech(MechCarrying(mech));
00194 DOCHECKMA0(!map->cf, "The entrance is still filled with rubble!");
00195 MechLOSBroadcast(mech, "has left the hangar.");
00196 mech_Rsetmapindex(GOD, (void *) mech, tprintf("%d",
00197 (int) map->
00198 mapobj[TYPE_LEAVE]->obj));
00199 if(car)
00200 mech_Rsetmapindex(GOD, (void *) car, tprintf("%d",
00201 (int) map->
00202 mapobj[TYPE_LEAVE]->
00203 obj));
00204 map = getMap(mech->mapindex);
00205 if(mech->mapindex == mapob) {
00206 SendError(tprintf("#%d %s attempted to leave, but no target map?",
00207 mech->mynum, GetMechID(mech)));
00208 mech_notify(mech, MECHALL,
00209 "Exit of this map is.. fubared. Please contact a wizard");
00210 return 0;
00211 }
00212 if(!(mapo = find_entrance_by_target(map, mapob))) {
00213 SendError(tprintf
00214 ("#%d %s attempted to leave, but no target place was found? setting the mech at 0,0 at %d.",
00215 mech->mynum, GetMechID(mech), mech->mapindex));
00216 mech_notify(mech, MECHALL,
00217 "Weird bug happened during leave. Please contact a wizard. ");
00218 return 1;
00219 }
00220
00221 StopBSuitSwarmers(FindObjectsData(mech->mapindex), mech, 1);
00222 mech_printf(mech, MECHALL, "You have left %s.", structure_name(mapo));
00223 mech_Rsetxy(GOD, (void *) mech, tprintf("%d %d", mapo->x, mapo->y));
00224 ContinueFlying(mech);
00225 if(car)
00226 MirrorPosition(mech, car, 0);
00227 MechLOSBroadcast(mech, tprintf("has left %s at %d,%d.",
00228 structure_name(mapo), MechX(mech),
00229 MechY(mech)));
00230 loud_teleport(mech->mynum, mech->mapindex);
00231 if(car)
00232 loud_teleport(car->mynum, mech->mapindex);
00233 if(In_Character(mech->mynum) && Location(MechPilot(mech)) != mech->mynum) {
00234 mech_notify(mech, MECHALL,
00235 "%ch%cr%cf%ciINTRUDER ALERT! INTRUDER ALERT!%c");
00236 mech_notify(mech, MECHALL,
00237 "%ch%cr%cfAutomatic self-destruct sequence initiated...%c");
00238 mech_shutdown(GOD, (void *) mech, "");
00239 }
00240 auto_cal_mapindex(mech);
00241 if(MechSpeed(mech) > MMaxSpeed(mech))
00242 MechSpeed(mech) = MMaxSpeed(mech);
00243 return 1;
00244 }
00245
00246 void CheckEdgeOfMap(MECH * mech)
00247 {
00248 int pinned = 0;
00249 int linked;
00250 MAP *map;
00251
00252 map = getMap(mech->mapindex);
00253
00254 if(!map) {
00255 mech_notify(mech, MECHPILOT,
00256 "You are on an invalid map! Map index reset!");
00257 mech_shutdown(MechPilot(mech), (void *) mech, "");
00258 SendError(tprintf("CheckEdgeofMap:invalid map:Mech: %d Index: %d",
00259 mech->mynum, mech->mapindex));
00260 mech->mapindex = -1;
00261 return;
00262 }
00263 linked = map_linked(mech->mapindex);
00264
00265
00266 if(MechX(mech) < 0) {
00267 if(linked) {
00268 MechX(mech) += map->map_width;
00269 pinned = -1;
00270 } else {
00271 MechX(mech) = 0;
00272 pinned = 4;
00273 }
00274 } else if(MechX(mech) >= map->map_width) {
00275 if(linked) {
00276 MechX(mech) -= map->map_width;
00277 pinned = -1;
00278 } else {
00279 MechX(mech) = map->map_width - 1;
00280 pinned = 2;
00281 }
00282 }
00283 if(MechY(mech) < 0) {
00284 if(linked) {
00285 pinned = -1;
00286 MechY(mech) += map->map_height;
00287 } else {
00288 MechY(mech) = 0;
00289 pinned = 1;
00290 }
00291 } else if(MechY(mech) >= map->map_height) {
00292 if(linked) {
00293 pinned = -1;
00294 MechY(mech) -= map->map_height;
00295 } else {
00296 MechY(mech) = map->map_height - 1;
00297 pinned = 3;
00298 }
00299 }
00300 if(pinned > 0) {
00301
00302
00303
00304 if(map->onmap && IsMech(map->onmap)) {
00305 if(Leave_DS(map, mech))
00306 return;
00307 } else if(map->flags & MAPFLAG_MAPO && map->mapobj[TYPE_LEAVE])
00308 if(Leave_Hangar(map, mech))
00309 return;
00310 }
00311 if(pinned) {
00312 MapCoordToRealCoord(MechX(mech), MechY(mech), &MechFX(mech),
00313 &MechFY(mech));
00314 if(pinned > 0) {
00315 mech_notify(mech, MECHALL, "You cannot move off this map!");
00316 if(Jumping(mech) && !is_aero(mech))
00317 LandMech(mech);
00318 MechCocoon(mech) = 0;
00319 MechSpeed(mech) = 0.0;
00320 MechDesiredSpeed(mech) = 0.0;
00321 if(is_aero(mech)) {
00322 MechStartFX(mech) = 0.0;
00323 MechStartFY(mech) = 0.0;
00324 MechStartFZ(mech) = 0.0;
00325 if(!Landed(mech))
00326 MaybeMove(mech);
00327 }
00328 }
00329 }
00330 }
00331 int FindZBearing(float x0, float y0, float z0, float x1, float y1, float z1)
00332 {
00333 float adj, opp, deg;
00334
00335 adj = FindXYRange(x0, y0, x1, y1);
00336
00337
00338
00339
00340 opp = (float)(1./SCALEMAP) * fabsf(z1 - z0);
00341
00342 deg = RAD2DEG(atan2(opp, adj));
00343 return ceilf(deg);
00344 }
00345
00346 int FindBearing(float x0, float y0, float x1, float y1)
00347 {
00348 const float dx = x1 - x0;
00349 const float dy = y1 - y0;
00350
00351 float rads;
00352 int degrees;
00353
00354
00355
00356
00357
00358 if (dx == 0.f) {
00359 return (dy < 0.f) ? 0 : 180;
00360 }
00361
00362
00363 rads = (float)atan2(-dx, dy);
00364
00365
00366 degrees = ((int)RAD2DEG(10.f * rads) + 5) / 10;
00367
00368 return AcceptableDegree(degrees + 180);
00369 }
00370
00371 int InWeaponArc(MECH * mech, float x, float y)
00372 {
00373 int relat;
00374 int bearingToTarget;
00375 int res = NOARC;
00376
00377 bearingToTarget = FindBearing(MechFX(mech), MechFY(mech), x, y);
00378 relat = MechFacing(mech) - bearingToTarget;
00379 if(MechType(mech) == CLASS_MECH || MechType(mech) == CLASS_MW ||
00380 MechType(mech) == CLASS_BSUIT) {
00381 if(MechStatus(mech) & TORSO_RIGHT)
00382 relat += 59;
00383 else if(MechStatus(mech) & TORSO_LEFT)
00384 relat -= 59;
00385 }
00386 relat = AcceptableDegree(relat);
00387 if(relat >= 300 || relat <= 60)
00388 res |= FORWARDARC;
00389 if(relat > 120 && relat < 240)
00390 res |= REARARC;
00391 if(relat >= 240 && relat < 300)
00392 res |= RSIDEARC;
00393 if(relat > 60 && relat <= 120)
00394 res |= LSIDEARC;
00395
00396 if(MechHasTurret(mech)) {
00397 relat = AcceptableDegree((MechFacing(mech) + MechTurretFacing(mech))
00398 - bearingToTarget);
00399 if(relat >= 330 || relat <= 30)
00400 res |= TURRETARC;
00401 }
00402 if(res == NOARC)
00403 SendError(tprintf("NoArc: #%d: BearingToTarget:%d Facing:%d",
00404 mech->mynum, bearingToTarget, MechFacing(mech)));
00405 return res;
00406 }
00407
00408 char *FindGunnerySkillName(MECH * mech, int weapindx)
00409 {
00410 #ifndef BT_EXILE_MW3STATS
00411 switch (MechType(mech)) {
00412 case CLASS_BSUIT:
00413 return "Gunnery-BSuit";
00414 case CLASS_MECH:
00415 return "Gunnery-Battlemech";
00416 case CLASS_VEH_GROUND:
00417 case CLASS_VEH_NAVAL:
00418 return "Gunnery-Conventional";
00419 case CLASS_VTOL:
00420 case CLASS_AERO:
00421 return "Gunnery-Aerospace";
00422 case CLASS_SPHEROID_DS:
00423 case CLASS_DS:
00424 return "Gunnery-Spacecraft";
00425 case CLASS_MW:
00426 if(weapindx >= 0) {
00427 if(!strcmp(MechWeapons[weapindx].name, "PC.Sword"))
00428 return "Blade";
00429 if(!strcmp(MechWeapons[weapindx].name, "PC.Vibroblade"))
00430 return "Blade";
00431 }
00432 return "Small_Arms";
00433 }
00434 #else
00435 if(weapindx < 0)
00436 return NULL;
00437 if(MechType(mech) == CLASS_MW) {
00438 if(weapindx >= 0) {
00439 if(!strcmp(MechWeapons[weapindx].name, "PC.Blade"))
00440 return "Blade";
00441 if(!strcmp(MechWeapons[weapindx].name, "PC.Vibroblade"))
00442 return "Blade";
00443 if(!strcmp(MechWeapons[weapindx].name, "PC.Blazer"))
00444 return "Support_Weapons";
00445 if(!strcmp(MechWeapons[weapindx].name, "PC.HeavyGyrojetGun"))
00446 return "Support_Weapons";
00447 return "Small_Arms";
00448 }
00449 } else if(IsArtillery(weapindx))
00450 return "Gunnery-Artillery";
00451 else if(IsMissile(weapindx))
00452 return "Gunnery-Missile";
00453 else if(IsBallistic(weapindx))
00454 return "Gunnery-Ballistic";
00455 else if(IsEnergy(weapindx))
00456 return "Gunnery-Laser";
00457 else if(IsFlamer(weapindx))
00458 return "Gunnery-Flamer";
00459 #endif
00460 return NULL;
00461 }
00462
00463 char *FindPilotingSkillName(MECH * mech)
00464 {
00465 #ifndef BT_EXILE_MW3STATS
00466 switch (MechType(mech)) {
00467 case CLASS_MW:
00468 return "Running";
00469 case CLASS_BSUIT:
00470 return "Piloting-BSuit";
00471 case CLASS_MECH:
00472 return "Piloting-Battlemech";
00473 case CLASS_VEH_GROUND:
00474 case CLASS_VEH_NAVAL:
00475 return "Drive";
00476 case CLASS_VTOL:
00477 case CLASS_AERO:
00478 return "Piloting-Aerospace";
00479 case CLASS_SPHEROID_DS:
00480 case CLASS_DS:
00481 return "Piloting-Spacecraft";
00482 }
00483 #else
00484 if(MechType(mech) == CLASS_MW && MechRTerrain(mech) == WATER)
00485 return "Swimming";
00486 switch (MechType(mech)) {
00487 case CLASS_MW:
00488 return "Running";
00489 case CLASS_BSUIT:
00490 return "Piloting-Bsuit";
00491 case CLASS_VEH_NAVAL:
00492 return "Piloting-Naval";
00493 case CLASS_DS:
00494 case CLASS_SPHEROID_DS:
00495 return "Piloting-Spacecraft";
00496 case CLASS_VTOL:
00497 case CLASS_AERO:
00498 return "Piloting-Aerospace";
00499 }
00500 switch (MechMove(mech)) {
00501 case MOVE_BIPED:
00502 return "Piloting-Biped";
00503 case MOVE_QUAD:
00504 return "Piloting-Quad";
00505 case MOVE_TRACK:
00506 return "Piloting-Tracked";
00507 case MOVE_HOVER:
00508 return "Piloting-Hover";
00509 case MOVE_WHEEL:
00510 return "Piloting-Wheeled";
00511 }
00512 #endif
00513 return NULL;
00514 }
00515
00516 #define MECHSKILL_PILOTING 0
00517 #define MECHSKILL_GUNNERY 1
00518 #define MECHSKILL_SPOTTING 2
00519 #define MECHSKILL_ARTILLERY 3
00520 #define NUM_MECHSKILLS 4
00521
00522
00523 #define GENERIC_FIND_MECHSKILL(num,n) \
00524 if (Quiet(mech->mynum)) \
00525 { str = silly_atr_get(mech->mynum, A_MECHSKILLS); \
00526 if (*str) if (sscanf (str, "%d %d %d %d", &i[0], &i[1], &i[2], &i[3]) > num) \
00527 return i[num] - n; }
00528
00529 int FindPilotPiloting(MECH * mech)
00530 {
00531 char *str;
00532 int i[NUM_MECHSKILLS];
00533
00534 GENERIC_FIND_MECHSKILL(MECHSKILL_PILOTING, 0);
00535 if(RGotPilot(mech))
00536 if((str = FindPilotingSkillName(mech)))
00537 return char_getskilltarget(MechPilot(mech), str, 0);
00538 return DEFAULT_PILOTING;
00539 }
00540
00541 int FindSPilotPiloting(MECH * mech)
00542 {
00543 return FindPilotPiloting(mech) + (MechMove(mech) == MOVE_QUAD ? -2 : 0);
00544 }
00545
00546 int FindPilotSpotting(MECH * mech)
00547 {
00548 char *str;
00549 int i[NUM_MECHSKILLS];
00550
00551 GENERIC_FIND_MECHSKILL(MECHSKILL_SPOTTING, 0);
00552 if(RGotPilot(mech))
00553 return (char_getskilltarget(MechPilot(mech), "Gunnery-Spotting", 0));
00554 return DEFAULT_SPOTTING;
00555 }
00556
00557 int FindPilotArtyGun(MECH * mech)
00558 {
00559 char *str;
00560 int i[NUM_MECHSKILLS];
00561
00562 GENERIC_FIND_MECHSKILL(MECHSKILL_ARTILLERY, 0);
00563 if(RGotGPilot(mech))
00564 return (char_getskilltarget(GunPilot(mech), "Gunnery-Artillery", 0));
00565 return DEFAULT_ARTILLERY;
00566 }
00567
00568 int FindPilotGunnery(MECH * mech, int weapindx)
00569 {
00570 char *str;
00571 int i[NUM_MECHSKILLS];
00572
00573 GENERIC_FIND_MECHSKILL(MECHSKILL_GUNNERY, 0);
00574 if(RGotGPilot(mech))
00575 if((str = FindGunnerySkillName(mech, weapindx)))
00576 return char_getskilltarget(GunPilot(mech), str, 0);
00577 return DEFAULT_GUNNERY;
00578 }
00579
00580 char *FindTechSkillName(MECH * mech)
00581 {
00582 switch (MechType(mech)) {
00583 case CLASS_MECH:
00584 case CLASS_BSUIT:
00585 return "Technician-Battlemech";
00586 case CLASS_VEH_GROUND:
00587 case CLASS_VEH_NAVAL:
00588 return "Technician-Mechanic";
00589 case CLASS_AERO:
00590 case CLASS_VTOL:
00591 case CLASS_SPHEROID_DS:
00592 case CLASS_DS:
00593 return "Technician-Aerospace";
00594 #if 0
00595 return (char_getskilltarget(player, "Technician-Spacecraft", 0));
00596 #endif
00597 }
00598 return NULL;
00599 }
00600
00601 int FindTechSkill(dbref player, MECH * mech)
00602 {
00603 char *skname;
00604
00605 if((skname = FindTechSkillName(mech)))
00606 return (char_getskilltarget(player, skname, 0));
00607 return 18;
00608 }
00609
00610 int MadePilotSkillRoll(MECH * mech, int mods)
00611 {
00612 return MadePilotSkillRoll_Advanced(mech, mods, 1);
00613 }
00614
00615 int MechPilotSkillRoll_BTH(MECH * mech, int mods)
00616 {
00617 mods += FindSPilotPiloting(mech) + MechPilotSkillBase(mech);
00618 if(In_Character(mech->mynum) && Location(MechPilot(mech)) != mech->mynum)
00619 mods += 5;
00620 return mods;
00621 }
00622
00623 int MadePilotSkillRoll_NoXP(MECH * mech, int mods, int succeedWhenFallen)
00624 {
00625 int roll, roll_needed;
00626
00627 if(Fallen(mech) && succeedWhenFallen)
00628 return 1;
00629 if(Uncon(mech) || !Started(mech) || Blinded(mech))
00630 return 0;
00631 roll = Roll();
00632 roll_needed = MechPilotSkillRoll_BTH(mech, mods);
00633
00634 SendDebug(tprintf("Attempting to make pilot skill roll. "
00635 "SPilot: %d, mods: %d, MechPilot: %d, BTH: %d",
00636 FindSPilotPiloting(mech), mods,
00637 MechPilotSkillBase(mech), roll_needed));
00638
00639 mech_notify(mech, MECHPILOT, "You make a piloting skill roll!");
00640 mech_printf(mech, MECHPILOT,
00641 "Modified Pilot Skill: BTH %d\tRoll: %d", roll_needed, roll);
00642 if(roll >= roll_needed) {
00643 return 1;
00644 }
00645 return 0;
00646 }
00647
00648 int MadePilotSkillRoll_Advanced(MECH * mech, int mods, int succeedWhenFallen)
00649 {
00650 int roll, roll_needed;
00651
00652 if(Fallen(mech) && succeedWhenFallen)
00653 return 1;
00654 if(Uncon(mech) || !Started(mech) || Blinded(mech))
00655 return 0;
00656 roll = Roll();
00657 roll_needed = MechPilotSkillRoll_BTH(mech, mods);
00658
00659 SendDebug(tprintf("Attempting to make pilot (noxp) skill roll. "
00660 "SPilot: %d, mods: %d, MechPilot: %d, BTH: %d",
00661 FindSPilotPiloting(mech), mods,
00662 MechPilotSkillBase(mech), roll_needed));
00663
00664 mech_notify(mech, MECHPILOT, "You make a piloting skill roll!");
00665 mech_printf(mech, MECHPILOT,
00666 "Modified Pilot Skill: BTH %d\tRoll: %d", roll_needed, roll);
00667 if(roll >= roll_needed) {
00668 if(roll_needed > 2)
00669 AccumulatePilXP(MechPilot(mech), mech, BOUNDED(1,
00670 roll_needed - 7,
00671 MAX(2, 1 + mods)),
00672 1);
00673 return 1;
00674 }
00675 return 0;
00676 }
00677
00678 void FindXY(float x0, float y0, int bearing, float range, float *x1, float *y1)
00679 {
00680 float xscale, correction;
00681
00682
00683 correction = (float) (bearing % 60) / 60.0;
00684 if(correction > 0.5)
00685 correction = 1.0 - correction;
00686 correction = -correction * 2.0;
00687 xscale = (1.0 + XSCALE * correction) * SCALEMAP;
00688
00689
00690 *x1 = x0 + range * (float)sin(DEG2RAD(bearing)) * xscale;
00691 *y1 = y0 - range * (float)cos(DEG2RAD(bearing)) * SCALEMAP;
00692 }
00693
00694
00695 float FindRange(float x0, float y0, float z0, float x1, float y1, float z1)
00696 {
00697 const float dx = x0 - x1;
00698 const float dy = y0 - y1;
00699 const float dz = z0 - z1;
00700
00701
00702 return (float)(1./SCALEMAP) * (float)sqrt(dx * dx + dy * dy + dz * dz);
00703 }
00704
00705
00706 float FindXYRange(float x0, float y0, float x1, float y1)
00707 {
00708 const float dx = x0 - x1;
00709 const float dy = y0 - y1;
00710
00711
00712 return (float)(1./SCALEMAP) * (float)sqrt(dx * dx + dy * dy);
00713 }
00714
00715
00716 float FindHexRange(float x0, float y0, float x1, float y1)
00717 {
00718 return FindXYRange(x0, y0, x1, y1);
00719 }
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763 #define ROOT3 558.58638544096289
00764 #define ALPHA 93.097730906827152
00765 #define ANGLE_ALPHA 0.28867513459481287
00766 #define FULL_Y (1 * SCALEMAP)
00767 #define HALF_Y (0.5 * FULL_Y)
00768
00769 void RealCoordToMapCoord(short *hex_x, short *hex_y, float cart_x,
00770 float cart_y)
00771 {
00772 float x, y;
00773 int x_count, y_count;
00774
00775 if(cart_x < ALPHA) {
00776
00777 *hex_x = cart_x < 0 ? -1 : 0;
00778 *hex_y = floor(cart_y / SCALEMAP);
00779 return;
00780 }
00781
00782
00783 cart_x -= ALPHA;
00784
00785
00786 x_count = cart_x / ROOT3;
00787
00788 x = cart_x - x_count * ROOT3;
00789
00790
00791 x_count *= 2;
00792
00793
00794 y_count = floor(cart_y / FULL_Y);
00795 y = cart_y - y_count * FULL_Y;
00796
00797 if(x < 2 * ALPHA) {
00798
00799
00800
00801 } else if(x >= 3 * ALPHA && x < 5 * ALPHA) {
00802
00803
00804 x_count++;
00805 if(y >= HALF_Y)
00806
00807 y_count++;
00808
00809 } else if(x >= 2 * ALPHA && x < 3 * ALPHA) {
00810
00811 if(y >= HALF_Y) {
00812
00813 if(2 * ANGLE_ALPHA * (FULL_Y - y) <= x - 2 * ALPHA) {
00814
00815 x_count++;
00816 y_count++;
00817 }
00818 } else {
00819
00820 if(2 * ANGLE_ALPHA * y <= x - 2 * ALPHA)
00821
00822 x_count++;
00823 }
00824 } else if(y >= HALF_Y) {
00825
00826 x_count++;
00827 if(2 * ANGLE_ALPHA * (y - HALF_Y) > (x - 5.0 * ALPHA))
00828
00829 y_count++;
00830 else
00831
00832 x_count++;
00833 } else {
00834
00835 x_count++;
00836 if(2 * ANGLE_ALPHA * y > ROOT3 - x)
00837
00838 x_count++;
00839 }
00840
00841 *hex_x = x_count;
00842 *hex_y = y_count;
00843 }
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854 void MapCoordToRealCoord(int hex_x, int hex_y, float *cart_x, float *cart_y)
00855 {
00856
00857 *cart_x = (2.f + 3.f * (float)hex_x) * ALPHA;
00858 *cart_y = ((hex_x & 0x1) ? 0 : HALF_Y) + ((float)hex_y * FULL_Y);
00859 }
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877 #define NAV_ROW_HEIGHT (FULL_Y / 9.0)
00878 #define NAV_COLUMN_WIDTH (4 * ALPHA / 21.0)
00879 #define NAV_Y_OFFSET 2
00880 #define NAV_X_OFFSET 4
00881 #define NAV_MAX_HEIGHT 2+9+2
00882 #define NAV_MAX_WIDTH 4+21+2
00883
00884 void navigate_sketch_mechs(MECH * mech, MAP * map, int x, int y,
00885 char buff[NAVIGATE_LINES][MBUF_SIZE])
00886 {
00887 float corner_fx, corner_fy, fx, fy;
00888 int i, row, column;
00889 MECH *other;
00890
00891 MapCoordToRealCoord(x, y, &corner_fx, &corner_fy);
00892 corner_fx -= 2 * ALPHA;
00893 corner_fy -= HALF_Y;
00894
00895 for(i = 0; i < map->first_free; i++) {
00896 if(map->mechsOnMap[i] < 0)
00897 continue;
00898 if(!(other = FindObjectsData(map->mechsOnMap[i])))
00899 continue;
00900 if(other == mech)
00901 continue;
00902 if(MechX(other) != x || MechY(other) != y)
00903 continue;
00904 if(!InLineOfSight(mech, other, x, y, 0.5))
00905 continue;
00906
00907 fx = MechFX(other) - corner_fx;
00908 column = fx / NAV_COLUMN_WIDTH + NAV_X_OFFSET;
00909
00910 fy = MechFY(other) - corner_fy;
00911 row = fy / NAV_ROW_HEIGHT + NAV_Y_OFFSET;
00912
00913 if(column < 0 || column > NAV_MAX_WIDTH ||
00914 row < 0 || row > NAV_MAX_HEIGHT)
00915 continue;
00916
00917 buff[row][column] = MechSeemsFriend(mech, other) ? 'x' : 'X';
00918 }
00919
00920
00921
00922 fx = MechFX(mech) - corner_fx;
00923 column = fx / NAV_COLUMN_WIDTH + NAV_X_OFFSET;
00924
00925 fy = MechFY(mech) - corner_fy;
00926 row = fy / NAV_ROW_HEIGHT + NAV_Y_OFFSET;
00927
00928 if(column < 0 || column > NAV_MAX_WIDTH ||
00929 row < 0 || row > NAV_MAX_HEIGHT)
00930 return;
00931
00932 buff[row][column] = '*';
00933 }
00934
00935 int FindTargetXY(MECH * mech, float *x, float *y, float *z)
00936 {
00937 MECH *tempMech;
00938
00939 if(MechTarget(mech) != -1) {
00940 tempMech = getMech(MechTarget(mech));
00941 if(tempMech) {
00942 *x = MechFX(tempMech);
00943 *y = MechFY(tempMech);
00944 *z = MechFZ(tempMech);
00945 return 1;
00946 }
00947 } else if(MechTargX(mech) != -1 && MechTargY(mech) != -1) {
00948 MapCoordToRealCoord(MechTargX(mech), MechTargY(mech), x, y);
00949 *z = (float) ZSCALE *(MechTargZ(mech));
00950
00951 return 1;
00952 }
00953 return 0;
00954 }
00955
00956 int global_silence = 0;
00957
00958 #define UGLYTEST \
00959 if (num_crits) \
00960 { \
00961 if (num_crits != (i = GetWeaponCrits (mech, lastweap))) \
00962 { \
00963 if (whine && !global_silence) \
00964 SendError (tprintf ("Error in the numcriticals for weapon on #%d! (Should be: %d, is: %d)", mech->mynum, i, num_crits)); \
00965 return -1; \
00966 } \
00967 num_crits = 0; \
00968 }
00969
00970
00971
00972
00973
00974 int FindWeapons_Advanced(MECH * mech, int index, unsigned char *weaparray,
00975 unsigned char *weapdataarray, int *critical,
00976 int whine)
00977 {
00978 int loop;
00979 int weapcount = 0;
00980 int temp, data, lastweap = -1;
00981 int num_crits = 0, i;
00982
00983 for(loop = 0; loop < MAX_WEAPS_SECTION; loop++) {
00984 temp = GetPartType(mech, index, loop);
00985 data = GetPartData(mech, index, loop);
00986 if(IsWeapon(temp)) {
00987 temp = Weapon2I(temp);
00988 if(weapcount == 0) {
00989 lastweap = temp;
00990 weapdataarray[weapcount] = data;
00991 weaparray[weapcount] = temp;
00992 critical[weapcount] = loop;
00993 weapcount++;
00994 num_crits = 1;
00995 continue;
00996 }
00997 if(!num_crits || temp != lastweap ||
00998 (num_crits == GetWeaponCrits(mech, temp))) {
00999 UGLYTEST;
01000 weaparray[weapcount] = temp;
01001 weapdataarray[weapcount] = data;
01002 critical[weapcount] = loop;
01003 lastweap = temp;
01004 num_crits = 1;
01005 weapcount++;
01006 } else
01007 num_crits++;
01008 } else
01009 UGLYTEST;
01010 }
01011 UGLYTEST;
01012 return (weapcount);
01013 }
01014
01015 int FindAmmunition(MECH * mech, unsigned char *weaparray,
01016 unsigned short *ammoarray, unsigned short *ammomaxarray,
01017 unsigned int *modearray, int returnall)
01018 {
01019 int loop;
01020 int weapcount = 0;
01021 int temp, data, mode;
01022 int index, i, j, duplicate;
01023
01024 for(index = 0; index < NUM_SECTIONS; index++)
01025 for(loop = 0; loop < MAX_WEAPS_SECTION; loop++) {
01026 temp = GetPartType(mech, index, loop);
01027 if(IsAmmo(temp)) {
01028 data = GetPartData(mech, index, loop);
01029 mode = (GetPartAmmoMode(mech, index, loop) & AMMO_MODES);
01030 temp = Ammo2Weapon(temp);
01031 duplicate = 0;
01032
01033 for(i = 0; i < weapcount; i++) {
01034 if(temp == weaparray[i] && mode == modearray[i]) {
01035 if(!(PartIsNonfunctional(mech, index, loop)))
01036 ammoarray[i] += data;
01037 ammomaxarray[i] += FullAmmo(mech, index, loop);
01038 duplicate = 1;
01039 }
01040 }
01041
01042 if(!duplicate) {
01043 weaparray[weapcount] = temp;
01044
01045 if(!(PartIsNonfunctional(mech, index, loop)))
01046 ammoarray[weapcount] = data;
01047 else
01048 ammoarray[weapcount] = 0;
01049
01050 ammomaxarray[weapcount] = FullAmmo(mech, index, loop);
01051 modearray[weapcount] = mode;
01052
01053 weapcount++;
01054 }
01055 }
01056 }
01057
01058 if (!returnall) {
01059 for(i = 0; i < weapcount; i++)
01060 if(!ammoarray[i]) {
01061 for(j = i + 1; j < weapcount; j++) {
01062 weaparray[j - 1] = weaparray[j];
01063 ammoarray[j - 1] = ammoarray[j];
01064 ammomaxarray[j - 1] = ammomaxarray[j];
01065 modearray[j - 1] = modearray[j];
01066 }
01067 i--;
01068 weapcount--;
01069 }
01070 }
01071 return (weapcount);
01072 }
01073
01074 int FindLegHeatSinks(MECH * mech)
01075 {
01076 int loop;
01077 int heatsinks = 0;
01078
01079 for(loop = 0; loop < NUM_CRITICALS; loop++) {
01080 if(GetPartType(mech, LLEG, loop) == I2Special((HEAT_SINK)) &&
01081 !PartIsNonfunctional(mech, LLEG, loop))
01082 heatsinks++;
01083 if(GetPartType(mech, RLEG, loop) == I2Special((HEAT_SINK)) &&
01084 !PartIsNonfunctional(mech, RLEG, loop))
01085 heatsinks++;
01086
01087
01088
01089
01090
01091 if(MechIsQuad(mech)) {
01092 if(GetPartType(mech, LARM, loop) == I2Special((HEAT_SINK)) &&
01093 !PartIsNonfunctional(mech, LARM, loop))
01094 heatsinks++;
01095 if(GetPartType(mech, RARM, loop) == I2Special((HEAT_SINK)) &&
01096 !PartIsNonfunctional(mech, RARM, loop))
01097 heatsinks++;
01098 }
01099 }
01100 return (heatsinks);
01101 }
01102
01103
01104
01105
01106
01107
01108 int FindWeaponNumberOnMech_Advanced(MECH * mech, int number, int *section,
01109 int *crit, int sight)
01110 {
01111 int loop;
01112 unsigned char weaparray[MAX_WEAPS_SECTION];
01113 unsigned char weapdata[MAX_WEAPS_SECTION];
01114 int critical[MAX_WEAPS_SECTION];
01115 int running_sum = 0;
01116 int num_weaps;
01117 int index;
01118
01119 for(loop = 0; loop < NUM_SECTIONS; loop++) {
01120 num_weaps = FindWeapons(mech, loop, weaparray, weapdata, critical);
01121
01122 if(num_weaps <= 0)
01123 continue;
01124
01125 if(number < running_sum + num_weaps) {
01126
01127 index = number - running_sum;
01128 if(PartIsNonfunctional(mech, loop, critical[index])) {
01129 *section = loop;
01130 *crit = critical[index];
01131 return TIC_NUM_DESTROYED;
01132 } else if(weapdata[index] > 0 && !sight) {
01133 *section = loop;
01134 *crit = critical[index];
01135 return (MechWeapons[weaparray[index]].type ==
01136 TBEAM) ? TIC_NUM_RECYCLING : TIC_NUM_RELOADING;
01137 } else {
01138
01139 if(MechSections(mech)[loop].recycle &&
01140 (MechType(mech) == CLASS_MECH ||
01141 MechType(mech) == CLASS_VEH_GROUND ||
01142 MechType(mech) == CLASS_VTOL) && !sight) {
01143
01144 *section = loop;
01145 *crit = critical[index];
01146
01147 return TIC_NUM_PHYSICAL;
01148 }
01149
01150
01151 *section = loop;
01152 *crit = critical[index];
01153 return weaparray[index];
01154 }
01155 } else
01156 running_sum += num_weaps;
01157 }
01158 return -1;
01159 }
01160
01161 int FindWeaponNumberOnMech(MECH * mech, int number, int *section, int *crit)
01162 {
01163 return FindWeaponNumberOnMech_Advanced(mech, number, section, crit, 0);
01164 }
01165
01166 int FindWeaponFromIndex(MECH * mech, int weapindx, int *section, int *crit)
01167 {
01168 int loop;
01169 unsigned char weaparray[MAX_WEAPS_SECTION];
01170 unsigned char weapdata[MAX_WEAPS_SECTION];
01171 int critical[MAX_WEAPS_SECTION];
01172 int num_weaps;
01173 int index;
01174
01175 for(loop = 0; loop < NUM_SECTIONS; loop++) {
01176 num_weaps = FindWeapons(mech, loop, weaparray, weapdata, critical);
01177 for(index = 0; index < num_weaps; index++)
01178 if(weaparray[index] == weapindx) {
01179 *section = loop;
01180 *crit = critical[index];
01181 if(!PartIsNonfunctional(mech, loop, index) &&
01182 !WpnIsRecycling(mech, loop, index))
01183 return 1;
01184
01185
01186 }
01187 }
01188 return 0;
01189 }
01190
01191 int FindWeaponIndex(MECH * mech, int number)
01192 {
01193 int loop;
01194 unsigned char weaparray[MAX_WEAPS_SECTION];
01195 unsigned char weapdata[MAX_WEAPS_SECTION];
01196 int critical[MAX_WEAPS_SECTION];
01197 int running_sum = 0;
01198 int num_weaps;
01199 int index;
01200
01201 if(number < 0)
01202 return -1;
01203 for(loop = 0; loop < NUM_SECTIONS; loop++) {
01204 num_weaps = FindWeapons(mech, loop, weaparray, weapdata, critical);
01205 if(num_weaps <= 0)
01206 continue;
01207 if(number < running_sum + num_weaps) {
01208
01209 index = number - running_sum;
01210 return weaparray[index];
01211 }
01212 running_sum += num_weaps;
01213 }
01214 return -1;
01215 }
01216
01217
01218 int FullAmmo(MECH * mech, int loc, int pos)
01219 {
01220 int baseammo;
01221
01222 baseammo = MechWeapons[Ammo2I(GetPartType(mech,loc,pos))].ammoperton;
01223 if((GetPartAmmoMode(mech, loc, pos) & AC_AP_MODE)
01224 || (GetPartAmmoMode(mech, loc, pos) & AC_PRECISION_MODE)
01225 || (GetPartFireMode(mech, loc, pos) & HALFTON_MODE)) {
01226 return baseammo >> 1;
01227 }
01228
01229 if((GetPartAmmoMode(mech, loc, pos) & AC_CASELESS_MODE)) {
01230 return baseammo << 1;
01231 }
01232
01233 return baseammo;
01234 }
01235
01236 int findAmmoInSection(MECH * mech, int section, int type, int nogof, int gof)
01237 {
01238 int wIter;
01239
01240
01241 for(wIter = 0; wIter < NUM_CRITICALS; wIter++) {
01242 if(GetPartType(mech, section, wIter) == type &&
01243 !PartIsNonfunctional(mech, section, wIter) && (!nogof ||
01244 !(GetPartAmmoMode
01245 (mech, section,
01246 wIter) & nogof))
01247 && (!gof || (GetPartAmmoMode(mech, section, wIter) & gof))) {
01248
01249 if(!PartIsNonfunctional(mech, section, wIter) &&
01250 GetPartData(mech, section, wIter) > 0)
01251 return wIter;
01252 }
01253 }
01254
01255 return -1;
01256 }
01257
01258 int FindAmmoForWeapon_sub(MECH * mech, int weapSection, int weapCritical,
01259 int weapindx, int start, int *section,
01260 int *critical, int nogof, int gof)
01261 {
01262 int loop;
01263 int foundSlot;
01264 int desired;
01265 int wCritType = 0;
01266 int wWeapSize = 0;
01267 int wFirstCrit = 0;
01268 int wDesiredLoc = -1;
01269
01270 desired = I2Ammo(weapindx);
01271
01272
01273 if((weapSection > -1) && (weapCritical > -1)) {
01274 wCritType = GetPartType(mech, weapSection, weapCritical);
01275 wWeapSize = GetWeaponCrits(mech, Weapon2I(wCritType));
01276 wFirstCrit =
01277 FindFirstWeaponCrit(mech, weapSection, weapCritical, 0,
01278 wCritType, wWeapSize);
01279
01280 wDesiredLoc = GetPartDesiredAmmoLoc(mech, weapSection, wFirstCrit);
01281
01282 if(wDesiredLoc >= 0) {
01283 foundSlot =
01284 findAmmoInSection(mech, wDesiredLoc, desired, nogof, gof);
01285
01286 if(foundSlot >= 0) {
01287 *section = wDesiredLoc;
01288 *critical = foundSlot;
01289
01290 return 1;
01291 }
01292 }
01293 }
01294
01295
01296 foundSlot = findAmmoInSection(mech, start, desired, nogof, gof);
01297
01298 if(foundSlot >= 0) {
01299 *section = start;
01300 *critical = foundSlot;
01301
01302 return 1;
01303 }
01304
01305
01306 for(loop = 0; loop < NUM_SECTIONS; loop++) {
01307 if((loop == start) || (loop == wDesiredLoc))
01308 continue;
01309
01310 foundSlot = findAmmoInSection(mech, loop, desired, nogof, gof);
01311
01312 if(foundSlot >= 0) {
01313 *section = loop;
01314 *critical = foundSlot;
01315
01316 return 1;
01317 }
01318 }
01319
01320 return 0;
01321 }
01322
01323 int FindAmmoForWeapon(MECH * mech, int weapindx, int start, int *section,
01324 int *critical)
01325 {
01326 return FindAmmoForWeapon_sub(mech, -1, -1, weapindx, start, section,
01327 critical, AMMO_MODES, 0);
01328 }
01329
01330 int CountAmmoForWeapon(MECH * mech, int weapindx)
01331 {
01332 int wSecIter;
01333 int wSlotIter;
01334 int wcAmmo = 0;
01335 int wAmmoIdx;
01336
01337 wAmmoIdx = I2Ammo(weapindx);
01338
01339 for(wSecIter = 0; wSecIter < NUM_SECTIONS; wSecIter++) {
01340 for(wSlotIter = 0; wSlotIter < NUM_CRITICALS; wSlotIter++) {
01341 if((GetPartType(mech, wSecIter, wSlotIter) == wAmmoIdx) &&
01342 !PartIsNonfunctional(mech, wSecIter, wSlotIter) &&
01343 (GetPartData(mech, wSecIter, wSlotIter) > 0))
01344 wcAmmo += GetPartData(mech, wSecIter, wSlotIter);
01345 }
01346 }
01347
01348 return wcAmmo;
01349 }
01350
01351 int FindArtemisForWeapon(MECH * mech, int section, int critical)
01352 {
01353 int critloop;
01354 int desired;
01355
01356 desired = I2Special(ARTEMIS_IV);
01357 for(critloop = 0; critloop < NUM_CRITICALS; critloop++)
01358 if(GetPartType(mech, section, critloop) == desired &&
01359 !PartIsNonfunctional(mech, section, critloop)) {
01360 if(GetPartData(mech, section, critloop) == critical)
01361 return 1;
01362 }
01363 return 0;
01364 }
01365
01366 int FindDestructiveAmmo(MECH * mech, int *section, int *critical)
01367 {
01368 int loop;
01369 int critloop;
01370 int maxdamage = 0;
01371 int damage;
01372 int weapindx;
01373 int i;
01374 int type, data;
01375
01376 for(loop = 0; loop < NUM_SECTIONS; loop++)
01377 for(critloop = 0; critloop < NUM_CRITICALS; critloop++)
01378 if(IsAmmo(GetPartType(mech, loop, critloop)) &&
01379 !PartIsDestroyed(mech, loop, critloop)) {
01380 data = GetPartData(mech, loop, critloop);
01381 type = GetPartType(mech, loop, critloop);
01382 weapindx = Ammo2WeaponI(type);
01383 damage = data * MechWeapons[weapindx].damage;
01384 if(MechWeapons[weapindx].special & GAUSS)
01385 continue;
01386 if(IsMissile(weapindx) || IsArtillery(weapindx)) {
01387 for(i = 0; MissileHitTable[i].key != -1; i++)
01388 if(MissileHitTable[i].key == weapindx)
01389 damage *= MissileHitTable[i].num_missiles[10];
01390 }
01391 if(damage > maxdamage) {
01392 *section = loop;
01393 *critical = critloop;
01394 maxdamage = damage;
01395 }
01396 }
01397 return (maxdamage);
01398 }
01399
01400 int FindInfernoAmmo(MECH * mech, int *section, int *critical)
01401 {
01402 int loop;
01403 int critloop;
01404 int maxdamage = 0;
01405 int damage;
01406 int weapindx;
01407 int i;
01408 int type, data;
01409 int mode;
01410
01411 for(loop = 0; loop < NUM_SECTIONS; loop++)
01412 for(critloop = 0; critloop < NUM_CRITICALS; critloop++)
01413 if(IsAmmo(GetPartType(mech, loop, critloop)) &&
01414 !PartIsDestroyed(mech, loop, critloop)) {
01415 data = GetPartData(mech, loop, critloop);
01416 type = GetPartType(mech, loop, critloop);
01417 mode = GetPartAmmoMode(mech, loop, critloop);
01418 if(!(mode & INFERNO_MODE))
01419 continue;
01420 weapindx = Ammo2WeaponI(type);
01421 damage = data * MechWeapons[weapindx].damage;
01422 if(MechWeapons[weapindx].special & GAUSS)
01423 continue;
01424 if(IsMissile(weapindx) || IsArtillery(weapindx)) {
01425 for(i = 0; MissileHitTable[i].key != -1; i++)
01426 if(MissileHitTable[i].key == weapindx)
01427 damage *= MissileHitTable[i].num_missiles[10];
01428 }
01429 if(damage > maxdamage) {
01430 *section = loop;
01431 *critical = critloop;
01432 maxdamage = damage;
01433 }
01434 }
01435 return (maxdamage);
01436 }
01437
01438 int FindRoundsForWeapon(MECH * mech, int weapindx)
01439 {
01440 int loop;
01441 int critloop;
01442 int desired;
01443 int found = 0;
01444
01445 desired = I2Ammo(weapindx);
01446 for(loop = 0; loop < NUM_SECTIONS; loop++)
01447 for(critloop = 0; critloop < NUM_CRITICALS; critloop++)
01448 if(GetPartType(mech, loop, critloop) == desired &&
01449 !PartIsNonfunctional(mech, loop, critloop))
01450 found += GetPartData(mech, loop, critloop);
01451 return found;
01452 }
01453
01454 char *quad_locs[NUM_SECTIONS + 1] = {
01455 "Front Left Leg",
01456 "Front Right Leg",
01457 "Left Torso",
01458 "Right Torso",
01459 "Center Torso",
01460 "Rear Left Leg",
01461 "Rear Right Leg",
01462 "Head",
01463 NULL
01464 };
01465
01466 char *mech_locs[NUM_SECTIONS + 1] = {
01467 "Left Arm",
01468 "Right Arm",
01469 "Left Torso",
01470 "Right Torso",
01471 "Center Torso",
01472 "Left Leg",
01473 "Right Leg",
01474 "Head",
01475 NULL
01476 };
01477
01478 char *bsuit_locs[NUM_BSUIT_MEMBERS + 1] = {
01479 "Suit 1",
01480 "Suit 2",
01481 "Suit 3",
01482 "Suit 4",
01483 "Suit 5",
01484 "Suit 6",
01485 "Suit 7",
01486 "Suit 8",
01487 NULL
01488 };
01489
01490 char *veh_locs[NUM_VEH_SECTIONS + 1] = {
01491 "Left Side",
01492 "Right Side",
01493 "Front Side",
01494 "Aft Side",
01495 "Turret",
01496 "Rotor",
01497 NULL
01498 };
01499
01500 char *aero_locs[NUM_AERO_SECTIONS + 1] = {
01501 "Nose",
01502 "Left Wing",
01503 "Right Wing",
01504 "Aft Side",
01505 NULL
01506 };
01507
01508 char *ds_locs[NUM_DS_SECTIONS + 1] = {
01509 "Right Wing",
01510 "Left Wing",
01511 "Left Rear Wing",
01512 "Right Rear Wing",
01513 "Aft",
01514 "Nose",
01515 NULL
01516 };
01517
01518 char *ds_spher_locs[NUM_DS_SECTIONS + 1] = {
01519 "Front Right Side",
01520 "Front Left Side",
01521 "Rear Left Side",
01522 "Rear Right Side",
01523 "Aft",
01524 "Nose",
01525 NULL
01526 };
01527
01528 char **ProperSectionStringFromType(int type, int mtype)
01529 {
01530 switch (type) {
01531 case CLASS_BSUIT:
01532 return bsuit_locs;
01533 case CLASS_MECH:
01534 case CLASS_MW:
01535 if(mtype == MOVE_QUAD)
01536 return quad_locs;
01537 return mech_locs;
01538 case CLASS_VEH_GROUND:
01539 case CLASS_VEH_NAVAL:
01540 case CLASS_VTOL:
01541 return veh_locs;
01542 case CLASS_AERO:
01543 return aero_locs;
01544 case CLASS_SPHEROID_DS:
01545 return ds_spher_locs;
01546 case CLASS_DS:
01547 return ds_locs;
01548 }
01549 return NULL;
01550 }
01551
01552 void ArmorStringFromIndex(int index, char *buffer, char type, char mtype)
01553 {
01554 char **locs = ProperSectionStringFromType(type, mtype);
01555 int high = 0;
01556
01557 switch (type) {
01558 case CLASS_MECH:
01559 case CLASS_MW:
01560 high = NUM_SECTIONS;
01561 break;
01562 case CLASS_VEH_GROUND:
01563 case CLASS_VEH_NAVAL:
01564 high = (NUM_VEH_SECTIONS - 1);
01565 break;
01566 case CLASS_VTOL:
01567 high = NUM_VEH_SECTIONS;
01568 break;
01569 case CLASS_AERO:
01570 high = NUM_AERO_SECTIONS;
01571 break;
01572 case CLASS_SPHEROID_DS:
01573 high = NUM_DS_SECTIONS;
01574 case CLASS_DS:
01575 high = NUM_DS_SECTIONS;
01576 break;
01577 case CLASS_BSUIT:
01578 high = NUM_BSUIT_MEMBERS;
01579 break;
01580 default:
01581 strcpy(buffer, "Invalid!!");
01582 return;
01583 }
01584 if(high > 0 && index < high && locs) {
01585 strcpy(buffer, locs[index]);
01586 return;
01587 }
01588 strcpy(buffer, "Invalid!!");
01589 }
01590
01591 int IsInWeaponArc(MECH * mech, float x, float y, int section, int critical)
01592 {
01593 int weaponarc, isrear;
01594 int wantarc = NOARC;
01595
01596 if(MechType(mech) == CLASS_MECH && (section == LLEG || section == RLEG
01597 || (MechIsQuad(mech)
01598 && (section == LARM
01599 || section == RARM)))) {
01600 int ts = MechStatus(mech) & (TORSO_LEFT | TORSO_RIGHT);
01601 MechStatus(mech) &= ~(ts);
01602 weaponarc = InWeaponArc(mech, x, y);
01603 MechStatus(mech) |= ts;
01604 } else
01605 weaponarc = InWeaponArc(mech, x, y);
01606
01607 switch (MechType(mech)) {
01608 case CLASS_MECH:
01609 case CLASS_BSUIT:
01610 case CLASS_MW:
01611 if(GetPartFireMode(mech, section, critical) & REAR_MOUNT)
01612 wantarc = REARARC;
01613 else if(section == LARM && (MechStatus(mech) & FLIPPED_ARMS))
01614 wantarc = REARARC | LSIDEARC;
01615 else if(section == LARM)
01616 wantarc = FORWARDARC | LSIDEARC;
01617 else if(section == RARM && (MechStatus(mech) & FLIPPED_ARMS))
01618 wantarc = REARARC | RSIDEARC;
01619 else if(section == RARM)
01620 wantarc = FORWARDARC | RSIDEARC;
01621 else
01622 wantarc = FORWARDARC;
01623 break;
01624 case CLASS_VEH_GROUND:
01625 case CLASS_VEH_NAVAL:
01626 case CLASS_VTOL:
01627 switch (section) {
01628 case TURRET:
01629 wantarc = TURRETARC;
01630 break;
01631 case FSIDE:
01632 wantarc = FORWARDARC;
01633 break;
01634 case LSIDE:
01635 wantarc = LSIDEARC;
01636 break;
01637 case RSIDE:
01638 wantarc = RSIDEARC;
01639 break;
01640 case BSIDE:
01641 wantarc = REARARC;
01642 break;
01643 }
01644 break;
01645 case CLASS_DS:
01646 switch (section) {
01647 case DS_NOSE:
01648 wantarc = FORWARDARC;
01649 break;
01650 case DS_LWING:
01651 case DS_LRWING:
01652 wantarc = LSIDEARC;
01653 break;
01654 case DS_RWING:
01655 case DS_RRWING:
01656 wantarc = RSIDEARC;
01657 break;
01658 case DS_AFT:
01659 wantarc = REARARC;
01660 break;
01661 }
01662 break;
01663 case CLASS_SPHEROID_DS:
01664 switch (section) {
01665 case DS_NOSE:
01666 wantarc = FORWARDARC;
01667 break;
01668 case DS_LWING:
01669 wantarc = FORWARDARC | LSIDEARC;
01670 break;
01671 case DS_LRWING:
01672 wantarc = REARARC | LSIDEARC;
01673 break;
01674 case DS_RWING:
01675 wantarc = FORWARDARC | RSIDEARC;
01676 break;
01677 case DS_RRWING:
01678 wantarc = REARARC | RSIDEARC;
01679 break;
01680 case DS_AFT:
01681 wantarc = REARARC;
01682 break;
01683 }
01684 break;
01685
01686 case CLASS_AERO:
01687 isrear = (GetPartFireMode(mech, section, critical) & REAR_MOUNT);
01688 switch (section) {
01689 case AERO_NOSE:
01690 wantarc = FORWARDARC | LSIDEARC | RSIDEARC;
01691 break;
01692 case AERO_LWING:
01693 wantarc = LSIDEARC | (isrear ? REARARC : FORWARDARC);
01694 break;
01695 case AERO_RWING:
01696 wantarc = RSIDEARC | (isrear ? REARARC : FORWARDARC);
01697 break;
01698 case AERO_AFT:
01699 wantarc = REARARC;
01700 break;
01701 }
01702 break;
01703 }
01704 return wantarc ? (wantarc & weaponarc) : 0;
01705 }
01706
01707 int GetWeaponCrits(MECH * mech, int weapindx)
01708 {
01709 return (MechType(mech) ==
01710 CLASS_MECH) ? (MechWeapons[weapindx].criticals) : 1;
01711 }
01712
01713 int listmatch(char **foo, char *mat)
01714 {
01715 int i;
01716
01717 for(i = 0; foo[i]; i++)
01718 if(!strcasecmp(foo[i], mat))
01719 return i;
01720 return -1;
01721 }
01722
01723
01724
01725
01726
01727
01728
01729
01730 void do_sub_magic(MECH * mech, int loud)
01731 {
01732 int jjs = 0;
01733 int hses = 0;
01734 int wanths, wanths_f;
01735 int shs_size = HS_Size(mech);
01736 int hs_eff = HS_Efficiency(mech);
01737 int i, j;
01738 int inthses = MechEngineSize(mech) / 25;
01739 int dest_hses = 0;
01740 int maxjjs = (int) ((float) MechMaxSpeed(mech) * MP_PER_KPH * 2 / 3);
01741
01742 if(MechSpecials(mech) & ICE_TECH)
01743 inthses = 0;
01744 for(i = 0; i < NUM_SECTIONS; i++)
01745 for(j = 0; j < CritsInLoc(mech, i); j++)
01746 switch (Special2I(GetPartType(mech, i, j))) {
01747 case HEAT_SINK:
01748 hses++;
01749 if(PartIsNonfunctional(mech, i, j))
01750 dest_hses++;
01751 break;
01752 case JUMP_JET:
01753 jjs++;
01754 break;
01755 }
01756 hses +=
01757 MIN(MechRealNumsinks(mech) * shs_size / hs_eff, inthses * shs_size);
01758 if(jjs > maxjjs) {
01759 if(loud)
01760 SendError(tprintf
01761 ("Error in #%d (%s): %d JJs, yet %d maximum available (due to walk MPs)?",
01762 mech->mynum, MechType_Ref(mech), jjs, maxjjs));
01763
01764 jjs = maxjjs;
01765 }
01766 MechJumpSpeed(mech) = MP1 * jjs;
01767 wanths_f = (hses / shs_size) * hs_eff;
01768 wanths = wanths_f - (dest_hses * hs_eff / shs_size);
01769 if(loud)
01770 MechNumOsinks(mech) =
01771 wanths - MIN(MechRealNumsinks(mech), inthses * hs_eff);
01772 if(wanths != MechRealNumsinks(mech) && loud) {
01773 SendError(tprintf
01774 ("Error in #%d (%s): Set HS: %d. Existing HS: %d. Difference: %d. Please %s.",
01775 mech->mynum, MechType_Ref(mech), MechRealNumsinks(mech),
01776 wanths, MechRealNumsinks(mech) - wanths,
01777 wanths <
01778 MechRealNumsinks(mech) ? "add the extra HS critical(s)" :
01779 "fix the template"));
01780 } else
01781 MechRealNumsinks(mech) = wanths;
01782 MechNumOsinks(mech) = wanths_f;
01783 }
01784
01785 #define CV(fun) fun(mech) = fun(&opp)
01786
01787
01788
01789
01790
01791
01792
01793
01794
01795
01796
01797
01798
01799
01800
01801
01802
01803
01804
01805 void do_magic(MECH * mech)
01806 {
01807 MECH opp;
01808 int i, j, t;
01809 int mask = 0;
01810 int tankCritMask = 0;
01811
01812 if(MechType(mech) != CLASS_MECH)
01813 tankCritMask =
01814 (TURRET_LOCKED | TURRET_JAMMED | TAIL_ROTOR_DESTROYED |
01815 CREW_STUNNED);
01816
01817
01818 StopBurning(mech);
01819 StopPerformingAction(mech);
01820
01821 memcpy(&opp, mech, sizeof(MECH));
01822 mech_loadnew(GOD, &opp, MechType_Ref(mech));
01823 MechEngineSizeV(mech) = MechEngineSizeC(&opp);
01824 opp.mynum = -1;
01825
01826 for(i = 0; i < NUM_SECTIONS; i++)
01827 for(j = 0; j < CritsInLoc(mech, i); j++) {
01828 SetPartType(&opp, i, j, GetPartType(mech, i, j));
01829 SetPartBrand(&opp, i, j, GetPartBrand(mech, i, j));
01830 SetPartData(&opp, i, j, 0);
01831 SetPartFireMode(&opp, i, j, 0);
01832 SetPartAmmoMode(&opp, i, j, 0);
01833 }
01834 if(MechType(mech) == CLASS_MECH)
01835 do_sub_magic(&opp, 0);
01836 MechNumOsinks(mech) = MechNumOsinks(&opp);
01837 for(i = 0; i < NUM_SECTIONS; i++) {
01838 if(MechType(mech) == CLASS_MECH) {
01839 for(j = 0; j < CritsInLoc(mech, i); j++) {
01840 if(PartIsDestroyed(mech, i, j)) {
01841 if(!PartIsDestroyed(&opp, i, j)) {
01842 if(!IsAmmo((t = GetPartType(mech, i, j)))) {
01843 if(!IsWeapon(t))
01844 HandleMechCrit(&opp, NULL, 0, i, j, t,
01845 GetPartData(mech, i, j));
01846 }
01847 }
01848 } else {
01849 t = GetPartType(mech, i, j);
01850 if(IsAMS(Weapon2I(t))) {
01851 if(MechWeapons[Weapon2I(t)].special & CLAT)
01852 MechSpecials(mech) |= CL_ANTI_MISSILE_TECH;
01853 else
01854 MechSpecials(mech) |= IS_ANTI_MISSILE_TECH;
01855 }
01856 GetPartFireMode(mech, i, j) &=
01857 ~(OS_USED | ROCKET_FIRED | IS_JETTISONED_MODE);
01858 }
01859 }
01860 }
01861
01862 MechSections(mech)[i].config &= ~STABILIZERS_DESTROYED;
01863
01864 if(SectIsDestroyed(mech, i))
01865 DestroySection(&opp, NULL, 0, i);
01866 if(MechStall(mech) > 0)
01867 UnSetSectBreached(mech, i);
01868 }
01869 CV(MechJumpSpeed);
01870 CV(MechMaxSpeed);
01871 CV(MechRealNumsinks);
01872 CV(MechEngineHeat);
01873 CV(MechPilotSkillBase);
01874 CV(MechLRSRange);
01875 CV(MechTacRange);
01876 CV(MechScanRange);
01877 CV(MechBTH);
01878 MechCritStatus(mech) &= mask;
01879 MechCritStatus(mech) |= MechCritStatus(&opp) & (~mask);
01880
01881 MechTankCritStatus(mech) &= tankCritMask;
01882 MechTankCritStatus(mech) |= MechTankCritStatus(&opp) & (~tankCritMask);
01883
01884 for(i = 0; i < NUM_SECTIONS; i++) {
01885 MechSections(mech)[i].basetohit = MechSections(&opp)[i].basetohit;
01886 MechSections(mech)[i].specials = MechSections(&opp)[i].specials;
01887 MechSections(mech)[i].specials &=
01888 ~(INARC_HOMING_ATTACHED | INARC_HAYWIRE_ATTACHED |
01889 INARC_ECM_ATTACHED | INARC_NEMESIS_ATTACHED);
01890 }
01891
01892
01893 if(!Destroyed(&opp) && Destroyed(mech))
01894 MechStatus(mech) &= ~DESTROYED;
01895 else if(Destroyed(&opp) && !Destroyed(mech))
01896 MechStatus(mech) |= DESTROYED;
01897 if(!Destroyed(mech) && MechType(mech) != CLASS_MECH)
01898 EvalBit(MechStatus(mech), FALLEN, Fallen(&opp));
01899 update_specials(mech);
01900 }
01901
01902 void mech_RepairPart(MECH * mech, int loc, int pos)
01903 {
01904 int t = GetPartType(mech, loc, pos);
01905
01906 UnDestroyPart(mech, loc, pos);
01907 if(IsWeapon(t) || IsAmmo(t)) {
01908 SetPartData(mech, loc, pos, 0);
01909 GetPartFireMode(mech, loc, pos) &=
01910 ~(OS_USED | IS_JETTISONED_MODE | ROCKET_FIRED);
01911 } else if(IsSpecial(t)) {
01912 switch (Special2I(t)) {
01913 case TARGETING_COMPUTER:
01914 case HEAT_SINK:
01915 case LIFE_SUPPORT:
01916 case COCKPIT:
01917 case SENSORS:
01918 case JUMP_JET:
01919 case ENGINE:
01920 case GYRO:
01921 case SHOULDER_OR_HIP:
01922 case LOWER_ACTUATOR:
01923 case UPPER_ACTUATOR:
01924 case HAND_OR_FOOT_ACTUATOR:
01925 case C3_MASTER:
01926 case C3_SLAVE:
01927 case C3I:
01928 case ECM:
01929 case ANGELECM:
01930 case NULL_SIGNATURE_SYSTEM:
01931 case BEAGLE_PROBE:
01932 case ARTEMIS_IV:
01933 case TAG:
01934 case BLOODHOUND_PROBE:
01935
01936 if(MechType(mech) == CLASS_MECH)
01937 do_magic(mech);
01938 break;
01939 }
01940 }
01941 }
01942
01943 int no_locations_destroyed(MECH * mech)
01944 {
01945 int i;
01946
01947 for(i = 0; i < NUM_SECTIONS; i++)
01948 if(GetSectOInt(mech, i) && SectIsDestroyed(mech, i))
01949 return 0;
01950 return 1;
01951 }
01952
01953 void mech_ReAttach(MECH * mech, int loc)
01954 {
01955 if(!SectIsDestroyed(mech, loc))
01956 return;
01957 UnSetSectDestroyed(mech, loc);
01958 UnSetSectFlooded(mech, loc);
01959 SetSectInt(mech, loc, GetSectOInt(mech, loc));
01960 if(is_aero(mech))
01961 SetSectInt(mech, loc, 1);
01962 if(MechType(mech) != CLASS_MECH) {
01963 if(no_locations_destroyed(mech) && IsDS(mech))
01964 MechStatus(mech) &= ~DESTROYED;
01965 return;
01966 }
01967 }
01968
01969 void mech_ReplaceSuit(MECH * mech, int loc)
01970 {
01971 if(!SectIsDestroyed(mech, loc))
01972 return;
01973
01974 UnSetSectDestroyed(mech, loc);
01975 SetSectInt(mech, loc, GetSectOInt(mech, loc));
01976 }
01977
01978
01979
01980
01981
01982
01983 void mech_ReSeal(MECH * mech, int loc)
01984 {
01985 int i;
01986
01987 if(SectIsDestroyed(mech, loc))
01988 return;
01989 if(!SectIsFlooded(mech, loc))
01990 return;
01991
01992 UnSetSectFlooded(mech, loc);
01993
01994 for(i = 0; i < CritsInLoc(mech, loc); i++) {
01995 if(PartIsDisabled(mech, loc, i)) {
01996 if(!PartIsBroken(mech, loc, i) && !PartIsDamaged(mech, loc, i))
01997 mech_RepairPart(mech, loc, i);
01998 else
01999 UnDisablePart(mech, loc, i);
02000 }
02001 }
02002 }
02003
02004 void mech_Detach(MECH * mech, int loc)
02005 {
02006 if(SectIsDestroyed(mech, loc))
02007 return;
02008 DestroySection(mech, NULL, 0, loc);
02009 }
02010
02011
02012
02013 void mech_FillPartAmmo(MECH * mech, int loc, int pos)
02014 {
02015 int t, to;
02016
02017 t = GetPartType(mech, loc, pos);
02018
02019 if(!IsAmmo(t))
02020 return;
02021 if(!(to = MechWeapons[Ammo2Weapon(t)].ammoperton))
02022 return;
02023 SetPartData(mech, loc, pos, FullAmmo(mech, loc, pos));
02024 }
02025
02026 int AcceptableDegree(int d)
02027 {
02028
02029
02030
02031
02032
02033 if (d < 0) {
02034 return (d % 360) + 360;
02035 } else if (d >= 360) {
02036 return (d % 360);
02037 } else {
02038 return d;
02039 }
02040 }
02041
02042 void MarkForLOSUpdate(MECH * mech)
02043 {
02044 MAP *mech_map;
02045
02046 if(!(mech_map = getMap(mech->mapindex)))
02047 return;
02048 mech_map->moves++;
02049 mech_map->mechflags[mech->mapnumber] = 1;
02050 }
02051
02052 void multi_weap_sel(MECH * mech, dbref player, char *buffer, int bitbybit,
02053 int (*foo) (MECH *, dbref, int, int))
02054 {
02055
02056
02057
02058
02059
02060
02061
02062 char *c;
02063 int i1, i2, i3;
02064 int section, critical;
02065
02066 skipws(buffer);
02067 if((c = strstr(buffer, ","))) {
02068 *c = 0;
02069 c++;
02070 }
02071 if(sscanf(buffer, "%d-%d", &i1, &i2) == 2) {
02072 DOCHECK(i1 < 0 ||
02073 i1 >= MAX_WEAPONS_PER_MECH,
02074 tprintf("Invalid first number in range (%d)", i1));
02075 DOCHECK(i2 < 0 ||
02076 i2 >= MAX_WEAPONS_PER_MECH,
02077 tprintf("Invalid second number in range (%d)", i2));
02078 if(i1 > i2) {
02079 i3 = i1;
02080 i1 = i2;
02081 i2 = i3;
02082 }
02083 } else {
02084 DOCHECK(Readnum(i1, buffer), tprintf("Invalid value: %s", buffer));
02085 DOCHECK(i1 < 0 ||
02086 i1 >= MAX_WEAPONS_PER_MECH,
02087 tprintf("Invalid weapon number: %d", i1));
02088 i2 = i1;
02089 }
02090 if(bitbybit / 2) {
02091 DOCHECK(i2 >= NUM_TICS, tprintf("There are only %d tics!", i2));
02092 } else {
02093 DOCHECK(!(FindWeaponNumberOnMech(mech, i2, §ion,
02094 &critical) != -1),
02095 tprintf("Error: the mech doesn't HAVE %d weapons!", i2 + 1));
02096 }
02097 if(bitbybit % 2) {
02098 for(i3 = i1; i3 <= i2; i3++)
02099 if(foo(mech, player, i3, i3))
02100 return;
02101 } else if(foo(mech, player, i1, i2))
02102 return;
02103 if(c)
02104 multi_weap_sel(mech, player, c, bitbybit, foo);
02105 }
02106
02107 int Roll()
02108 {
02109 int i = Number(1, 6) + Number(1, 6);
02110
02111 rollstat.rolls[i - 2]++;
02112 rollstat.totrolls++;
02113 return i;
02114 }
02115
02116 int MyHexDist(int x1, int y1, int x2, int y2, int tc)
02117 {
02118 int xd = abs(x2 - x1);
02119 int yd = abs(y2 - y1);
02120 int hm;
02121
02122
02123 if(x1 == x2)
02124 return yd;
02125
02126
02127
02128
02129
02130
02131 if((hm = (xd / 2)) <= yd)
02132 return (yd - hm) + tc + xd;
02133
02134
02135
02136
02137
02138
02139
02140 if(!yd)
02141 return (xd + tc);
02142
02143
02144
02145
02146
02147
02148
02149
02150 return (xd + tc);
02151 }
02152
02153 int CountDestroyedLegs(MECH * objMech)
02154 {
02155 int wcDeadLegs = 0;
02156
02157 if(MechType(objMech) != CLASS_MECH)
02158 return 0;
02159
02160 if(MechIsQuad(objMech)) {
02161 if(IsLegDestroyed(objMech, LARM))
02162 wcDeadLegs++;
02163
02164 if(IsLegDestroyed(objMech, RARM))
02165 wcDeadLegs++;
02166 }
02167
02168 if(IsLegDestroyed(objMech, LLEG))
02169 wcDeadLegs++;
02170
02171 if(IsLegDestroyed(objMech, RLEG))
02172 wcDeadLegs++;
02173
02174 return wcDeadLegs;
02175 }
02176
02177 int IsLegDestroyed(MECH * objMech, int wLoc)
02178 {
02179 return (SectIsDestroyed(objMech, wLoc) || SectIsBreached(objMech, wLoc)
02180 || SectIsFlooded(objMech, wLoc));
02181 }
02182
02183 int IsMechLegLess(MECH * objMech)
02184 {
02185 int wcMaxLegs = 0;
02186
02187 if(MechType(objMech) != CLASS_MECH)
02188 return 0;
02189
02190 if(MechIsQuad(objMech))
02191 wcMaxLegs = 4;
02192 else
02193 wcMaxLegs = 2;
02194
02195 if(CountDestroyedLegs(objMech) >= wcMaxLegs)
02196 return 1;
02197
02198 return 0;
02199 }
02200
02201 int FindFirstWeaponCrit(MECH * objMech, int wLoc, int wSlot,
02202 int wStartSlot, int wCritType, int wMaxCrits)
02203 {
02204 int wCritsInLoc = 0;
02205 int wCritIter, wFirstCrit;
02206
02207
02208
02209
02210
02211
02212 wFirstCrit = -1;
02213
02214 for(wCritIter = wStartSlot; wCritIter < NUM_CRITICALS; wCritIter++) {
02215 if(GetPartType(objMech, wLoc, wCritIter) == wCritType) {
02216 wCritsInLoc++;
02217
02218 if(wFirstCrit == -1)
02219 wFirstCrit = wCritIter;
02220 }
02221 }
02222
02223 if((wFirstCrit > -1) && (wSlot == -1))
02224 return wFirstCrit;
02225
02226
02227
02228
02229
02230
02231 if(wCritsInLoc > wMaxCrits) {
02232
02233
02234
02235
02236
02237 if((wFirstCrit + wMaxCrits) <= wSlot)
02238 wFirstCrit =
02239 FindFirstWeaponCrit(objMech, wLoc, wSlot,
02240 (wFirstCrit + wMaxCrits), wCritType,
02241 wMaxCrits);
02242 }
02243
02244 return wFirstCrit;
02245 }
02246
02247 int checkAllSections(MECH * mech, int specialToFind)
02248 {
02249 int i;
02250
02251 for(i = 0; i < NUM_SECTIONS; i++) {
02252 if(checkSectionForSpecial(mech, specialToFind, i))
02253 return 1;
02254 }
02255
02256 return 0;
02257 }
02258
02259 int checkSectionForSpecial(MECH * mech, int specialToFind, int wSec)
02260 {
02261 if(SectIsDestroyed(mech, wSec))
02262 return 0;
02263
02264 if(MechSections(mech)[wSec].specials & specialToFind)
02265 return 1;
02266
02267 return 0;
02268 }
02269
02270 int getRemainingInternalPercent(MECH * mech)
02271 {
02272 int i;
02273 float wMax = 0;
02274 float wRemaining = 0;
02275
02276 for(i = 0; i < NUM_SECTIONS; i++) {
02277 wMax += GetSectOInt(mech, i);
02278
02279 wRemaining += GetSectInt(mech, i);
02280 }
02281
02282 if(wMax == 0)
02283 return 0;
02284
02285 return ((wRemaining / wMax) * 100);
02286 }
02287
02288 int getRemainingArmorPercent(MECH * mech)
02289 {
02290 int i;
02291 float wMax = 0;
02292 float wRemaining = 0;
02293
02294 for(i = 0; i < NUM_SECTIONS; i++) {
02295 wMax += GetSectOArmor(mech, i);
02296 wMax += GetSectORArmor(mech, i);
02297
02298 wRemaining += GetSectArmor(mech, i);
02299 wRemaining += GetSectRArmor(mech, i);
02300 }
02301
02302 if(wMax == 0)
02303 return 0;
02304
02305 return ((wRemaining / wMax) * 100);
02306 }
02307
02308 int FindObj(MECH * mech, int loc, int type)
02309 {
02310 int count = 0, i;
02311
02312 for(i = 0; i < NUM_CRITICALS; i++)
02313 if(GetPartType(mech, loc, i) == type)
02314 if(!PartIsNonfunctional(mech, loc, i))
02315 count++;
02316 return count;
02317 }
02318
02319 int FindObjWithDest(MECH * mech, int loc, int type)
02320 {
02321 int count = 0, i;
02322
02323 for(i = 0; i < NUM_CRITICALS; i++)
02324 if(GetPartType(mech, loc, i) == type)
02325 count++;
02326 return count;
02327 }
02328
02329
02330
02331
02332
02333
02334
02335
02336
02337 MECH *find_mech_in_hex(MECH * mech, MAP * mech_map, int x, int y, int needlos)
02338 {
02339 int loop;
02340 MECH *target;
02341
02342 for(loop = 0; loop < mech_map->first_free; loop++)
02343 if(mech_map->mechsOnMap[loop] != mech->mynum &&
02344 mech_map->mechsOnMap[loop] != -1) {
02345 target = (MECH *) FindObjectsData(mech_map->mechsOnMap[loop]);
02346 if(!target)
02347 continue;
02348 if(!(MechX(target) == x && MechY(target) == y) && !(needlos & 2))
02349 continue;
02350 if(needlos) {
02351 if(needlos & 1)
02352 if(!InLineOfSight(mech, target, x, y,
02353 FlMechRange(mech_map, mech, target)))
02354 continue;
02355 if(needlos & 2) {
02356 if(MechTeam(mech) != MechTeam(target))
02357 continue;
02358 if(!(MechSeesHex(target, mech_map, x, y)))
02359 continue;
02360 if(mech == target)
02361 continue;
02362 }
02363 }
02364 return target;
02365 }
02366 return NULL;
02367 }
02368
02369 int FindAndCheckAmmo(MECH * mech,
02370 int weapindx,
02371 int section,
02372 int critical,
02373 int *ammoLoc,
02374 int *ammoCrit, int *ammoLoc1, int *ammoCrit1,
02375 int *wGattlingShots)
02376 {
02377 int mod, nmod = 0;
02378 int wMaxShots = 0;
02379 int wRoundsToCheck = 1;
02380 int wWeapMode = GetPartFireMode(mech, section, critical);
02381 int tResetMode = 0;
02382 dbref player = GunPilot(mech);
02383
02384
02385 if(MechWeapons[weapindx].type == TBEAM ||
02386 MechWeapons[weapindx].type == THAND)
02387 return 1;
02388
02389
02390 if(MechWeapons[weapindx].special == ROCKET) {
02391 DOCHECK0(wWeapMode & ROCKET_FIRED,
02392 "That weapon has already been used!");
02393 return 1;
02394 }
02395
02396
02397 if(wWeapMode & OS_MODE) {
02398 DOCHECK0(GetPartFireMode(mech, section, critical) & OS_USED,
02399 "That weapon has already been used!");
02400 return 1;
02401 }
02402
02403 if(MechWeapons[weapindx].special & RAC) {
02404 wMaxShots = CountAmmoForWeapon(mech, weapindx);
02405
02406 if((wWeapMode & RAC_TWOSHOT_MODE) && (wMaxShots < 2)) {
02407 GetPartFireMode(mech, section, critical) &= ~RAC_TWOSHOT_MODE;
02408
02409 return 1;
02410 }
02411
02412 if((wWeapMode & RAC_FOURSHOT_MODE) && (wMaxShots < 4)) {
02413 GetPartFireMode(mech, section, critical) &= ~RAC_FOURSHOT_MODE;
02414
02415 return 1;
02416 }
02417
02418 if((wWeapMode & RAC_SIXSHOT_MODE) && (wMaxShots < 6)) {
02419 GetPartFireMode(mech, section, critical) &= ~RAC_SIXSHOT_MODE;
02420
02421 return 1;
02422 }
02423 }
02424
02425 if(wWeapMode & GATTLING_MODE) {
02426 wMaxShots = CountAmmoForWeapon(mech, weapindx);
02427
02428
02429
02430
02431
02432 if((wMaxShots / 3) < *wGattlingShots)
02433 *wGattlingShots = MAX((wMaxShots / 3), 1);
02434 }
02435
02436 if((wWeapMode & ULTRA_MODE) || (wWeapMode & RFAC_MODE))
02437 wRoundsToCheck = 2;
02438
02439 mod = GetPartAmmoMode(mech, section, critical) & AMMO_MODES;
02440
02441 if(!mod) {
02442 DOCHECK0(!FindAmmoForWeapon_sub(mech, section, critical, weapindx,
02443 section, ammoLoc, ammoCrit,
02444 AMMO_MODES, 0),
02445 "You don't have any ammo for that weapon stored on this mech!");
02446
02447 DOCHECK0(!GetPartData(mech, *ammoLoc, *ammoCrit),
02448 "You are out of ammo for that weapon!");
02449
02450 if(wRoundsToCheck > 1) {
02451 GetPartData(mech, *ammoLoc, *ammoCrit)--;
02452
02453 if(FindAmmoForWeapon_sub(mech, section, critical, weapindx,
02454 section, ammoLoc1, ammoCrit1, AMMO_MODES,
02455 0)) {
02456 if(!GetPartData(mech, *ammoLoc1, *ammoCrit1))
02457 tResetMode = 1;
02458 } else
02459 tResetMode = 1;
02460
02461 if(tResetMode)
02462 GetPartFireMode(mech, section, critical) &= ~wWeapMode;
02463
02464 GetPartData(mech, *ammoLoc, *ammoCrit)++;
02465 }
02466 } else {
02467 if(IsArtillery(weapindx))
02468 nmod = (~mod) & ARTILLERY_MODES;
02469 else
02470 nmod = (~mod) & AMMO_MODES;
02471 mod = (mod & AMMO_MODES);
02472
02473 DOCHECK0(!FindAmmoForWeapon_sub(mech, section, critical, weapindx,
02474 section, ammoLoc, ammoCrit, nmod,
02475 mod),
02476 "You don't have any ammo for that weapon stored on this mech!");
02477
02478 DOCHECK0(!GetPartData(mech, *ammoLoc, *ammoCrit),
02479 "You are out of the special ammo type for that weapon!");
02480
02481 if(wRoundsToCheck > 1) {
02482 GetPartData(mech, *ammoLoc, *ammoCrit)--;
02483
02484 if(FindAmmoForWeapon_sub(mech, section, critical, weapindx,
02485 section, ammoLoc1, ammoCrit1, nmod,
02486 mod)) {
02487 if(!GetPartData(mech, *ammoLoc1, *ammoCrit1))
02488 tResetMode = 1;
02489 } else
02490 tResetMode = 1;
02491
02492 if(tResetMode)
02493 GetPartFireMode(mech, section, critical) &= ~wWeapMode;
02494
02495 GetPartData(mech, *ammoLoc, *ammoCrit)++;
02496 }
02497 }
02498
02499 return 1;
02500 }
02501
02502 void ChannelEmitKill(MECH * mech, MECH * attacker)
02503 {
02504 if(!attacker)
02505 attacker = mech;
02506
02507 SendDebug(tprintf("#%d has been killed by #%d", mech->mynum,
02508 attacker->mynum));
02509 if(IsDS(mech))
02510 SendDSInfo(tprintf("#%d has been killed by #%d", mech->mynum,
02511 attacker->mynum));
02512 if(mech->mynum > 0 && attacker->mynum > 0)
02513 did_it(attacker->mynum, mech->mynum, 0, NULL, 0, NULL, A_AMECHDEST,
02514 (char **) NULL, 0);
02515 }
02516
02517 #define NUM_NEIGHBORS 6
02518 int dirs[6][2] = {
02519 {0, -1},
02520 {1, 0},
02521 {1, 1},
02522 {0, 1},
02523 {-1, 1},
02524 {-1, 0}
02525 };
02526
02527 void visit_neighbor_hexes(MAP * map, int tx, int ty,
02528 void (*callback) (MAP *, int, int))
02529 {
02530 int x1, y1;
02531 int i;
02532
02533 for(i = 0; i < NUM_NEIGHBORS; i++) {
02534 x1 = tx + dirs[i][0];
02535 y1 = ty + dirs[i][1];
02536 if(tx % 2 && !(x1 % 2))
02537 y1--;
02538 if(x1 < 0 || x1 >= map->map_width || y1 < 0 || y1 >= map->map_height)
02539 continue;
02540 callback(map, x1, y1);
02541 }
02542 }
02543
02544 int GetPartWeight(int part)
02545 {
02546 if(IsWeapon(part))
02547 return 10.24 * MechWeapons[Weapon2I(part)].weight;
02548 else if(IsAmmo(part))
02549 return 1024;
02550 else if(IsBomb(part))
02551 return 102 * BombWeight(Bomb2I(part));
02552 #ifndef BT_PART_WEIGHTS
02553 else if(IsSpecial(part) && part <= I2Special(CLAW))
02554 return 1024;
02555 #else
02556 else if(IsSpecial(part))
02557 return internalsweight[Special2I(part)];
02558 else if(IsCargo(part))
02559 return cargoweight[Cargo2I(part)];
02560 #endif
02561 else
02562
02563 return 102;
02564 }
02565
02566 #ifdef BT_ADVANCED_ECON
02567 unsigned long long int GetPartCost(int p)
02568 {
02569 extern unsigned long long int specialcost[SPECIALCOST_SIZE];
02570 extern unsigned long long int ammocost[AMMOCOST_SIZE];
02571 extern unsigned long long int weapcost[WEAPCOST_SIZE];
02572 extern unsigned long long int cargocost[CARGOCOST_SIZE];
02573 extern unsigned long long int bombcost[BOMBCOST_SIZE];
02574
02575 if(IsWeapon(p))
02576 return weapcost[Weapon2I(p)];
02577 else if(IsAmmo(p))
02578 return ammocost[Ammo2I(p)];
02579 else if(IsSpecial(p))
02580 return specialcost[Special2I(p)];
02581 else if(IsBomb(p))
02582 return bombcost[Bomb2I(p)];
02583 else if(IsCargo(p))
02584 return cargocost[Cargo2I(p)];
02585 else
02586 return 0;
02587 }
02588
02589 void SetPartCost(int p, unsigned long long int cost)
02590 {
02591 extern unsigned long long int specialcost[SPECIALCOST_SIZE];
02592 extern unsigned long long int ammocost[AMMOCOST_SIZE];
02593 extern unsigned long long int weapcost[WEAPCOST_SIZE];
02594 extern unsigned long long int cargocost[CARGOCOST_SIZE];
02595 extern unsigned long long int bombcost[BOMBCOST_SIZE];
02596
02597 if(IsWeapon(p))
02598 weapcost[Weapon2I(p)] = cost;
02599 else if(IsAmmo(p))
02600 ammocost[Ammo2I(p)] = cost;
02601 else if(IsSpecial(p))
02602 specialcost[Special2I(p)] = cost;
02603 else if(IsBomb(p))
02604 bombcost[Bomb2I(p)] = cost;
02605 else if(IsCargo(p))
02606 cargocost[Cargo2I(p)] = cost;
02607 }
02608
02609 #define COST_DEBUG 1
02610
02611 void CalcFasaCost_AddPrice(float * total, char * desc, float value) {
02612 *total += value;
02613 #if COST_DEBUG
02614 SendDebug(tprintf("Addprice - %20s %.0f", desc, value));
02615 #endif
02616 }
02617
02618 int MechNumHeatsinksInEngine(MECH * mech) {
02619
02620 return (MechEngineSize(mech) / 25);
02621 }
02622
02623 void CalcFasaCost_DoArmMath(MECH * mech, int loc, float * total) {
02624 int i = 0;
02625 for (i = 0; i < NUM_CRITICALS; i++) {
02626 int part = GetPartType(mech, loc, i);
02627 if (!IsActuator(part))
02628 continue;
02629 else if (Special2I(part) == SHOULDER_OR_HIP)
02630 continue;
02631
02632
02633 else if (Special2I(part) == UPPER_ACTUATOR)
02634 CalcFasaCost_AddPrice(total, "Upper Actuator", (MechTons(mech) * 100));
02635 else if (Special2I(part) == LOWER_ACTUATOR)
02636 CalcFasaCost_AddPrice(total, "Lower Actuator", (MechTons(mech) * 50));
02637 else if (Special2I(part) == HAND_OR_FOOT_ACTUATOR)
02638 CalcFasaCost_AddPrice(total, "Hand Actuator", (MechTons(mech) * 80));
02639 }
02640 }
02641
02642 void CalcFasaCost_DoLegMath(MECH * mech, int loc, float * total) {
02643 int i = 0;
02644 for (i = 0; i < NUM_CRITICALS; i++) {
02645 int part = GetPartType(mech, loc, i);
02646 if (!IsActuator(part))
02647 continue;
02648 else if (Special2I(part) == SHOULDER_OR_HIP ||
02649 Special2I(part) == UPPER_ACTUATOR)
02650 CalcFasaCost_AddPrice(total, "Hip Actuator", (MechTons(mech) * 150));
02651 else if (Special2I(part) == LOWER_ACTUATOR)
02652 CalcFasaCost_AddPrice(total, "Lower Actuator", (MechTons(mech) * 180));
02653 else if (Special2I(part) == HAND_OR_FOOT_ACTUATOR)
02654 CalcFasaCost_AddPrice(total, "Foot Actuator", (MechTons(mech) * 120));
02655 }
02656 }
02657
02658
02659
02660
02661
02662 unsigned long long int CalcFasaCost(MECH * mech)
02663 {
02664 int ii, i, part;
02665 float total = 0;
02666 float mod = 1.0;
02667
02668 if(!mech)
02669 return -1;
02670
02671 if(!
02672 (MechType(mech) == CLASS_MECH || MechType(mech) == CLASS_VEH_GROUND
02673 || MechType(mech) == CLASS_VEH_NAVAL || MechType(mech) == CLASS_VTOL
02674 || MechType(mech) == CLASS_BSUIT)
02675 || is_aero(mech) || IsDS(mech))
02676 return 0;
02677
02678 if(MechType(mech) == CLASS_MECH) {
02679
02680 #if 0
02681
02682 if(MechSpecials2(mech) & SMALLCOCKPIT_TECH)
02683 ADDPRICE("SmallCockpit", 175000)
02684 else
02685 if(MechSpecials2(mech) & TORSOCOCKPIT_TECH)
02686 ADDPRICE("TorsoCockpit", 750000)
02687 else
02688 #endif
02689 CalcFasaCost_AddPrice(&total, "Cockpit", 200000);
02690
02691
02692 CalcFasaCost_AddPrice(&total, "LifeSupport", 50000);
02693
02694
02695 CalcFasaCost_AddPrice(&total, "Sensors", (MechTons(mech) * 2000));
02696
02697
02698 if(MechSpecials(mech) & TRIPLE_MYOMER_TECH)
02699 CalcFasaCost_AddPrice(&total, "TS Myomer", (MechTons(mech) * 16000));
02700 else
02701 CalcFasaCost_AddPrice(&total, "Myomer", (MechTons(mech) * 2000));
02702
02703
02704 if(MechSpecials(mech) & ES_TECH || MechSpecials(mech) & COMPI_TECH)
02705 CalcFasaCost_AddPrice(&total, "ES/Co Internals", (MechTons(mech) * 1600));
02706 else if(MechSpecials(mech) & REINFI_TECH)
02707 CalcFasaCost_AddPrice(&total, "RE Internals", (MechTons(mech) * 6400));
02708 else
02709 CalcFasaCost_AddPrice(&total, "Internals", (MechTons(mech) * 400));
02710
02711
02712 CalcFasaCost_DoArmMath(mech, LARM, &total);
02713 CalcFasaCost_DoArmMath(mech, RARM, &total);
02714
02715
02716
02717
02718
02719 i = MechEngineSize(mech);
02720 if(i % 100)
02721 i += (100 - (MechEngineSize(mech) % 100));
02722 i /= 100;
02723
02724 if(MechSpecials2(mech) & XLGYRO_TECH)
02725 CalcFasaCost_AddPrice(&total, "XL Gyro", (i * 750000));
02726 else if(MechSpecials2(mech) & CGYRO_TECH)
02727 CalcFasaCost_AddPrice(&total, "Compact Gyro", (i * 400000));
02728 else if(MechSpecials2(mech) & HDGYRO_TECH)
02729 CalcFasaCost_AddPrice(&total, "HD Gyro", (i * 500000));
02730 else
02731 CalcFasaCost_AddPrice(&total, "Gyro", (i * 300000));
02732 } else if (MechType(mech) == CLASS_BSUIT) {
02733
02734
02735
02736 if (MechSpecials(mech) & CLAN_TECH) {
02737 CalcFasaCost_AddPrice(&total, "Clan Point", 3500000);
02738 } else {
02739 CalcFasaCost_AddPrice(&total, "IS Squad", 2400000);
02740 }
02741
02742 } else {
02743
02744
02745
02746 int pamp = 0, turret = 0;
02747
02748 for(i = 0; i < NUM_SECTIONS; i++)
02749 for(ii = 0; ii < NUM_CRITICALS; ii++) {
02750 if(!(part = GetPartType(mech, i, ii)))
02751 continue;
02752 if(!IsWeapon(part))
02753 continue;
02754 if(i == TURRET)
02755 turret += crit_weight(mech, part);
02756 if(IsEnergy(part)) {
02757 pamp += crit_weight(mech, part);
02758 SendDebug(tprintf("PAmp Weight: %d", crit_weight(mech, part)));
02759 }
02760 }
02761
02762
02763
02764
02765 int internals = (float)MechTons(mech) * 1000;
02766 CalcFasaCost_AddPrice(&total, "Internals", internals);
02767
02768
02769
02770
02771
02772 int control_eq = 10000 * 0.05 * MechTons(mech);
02773 CalcFasaCost_AddPrice(&total, "Cockpit & Controls", control_eq);
02774
02775
02776
02777
02778 if(MechSpecials(mech) & ICE_TECH) {
02779 int power_amp = 20000 * ( pamp / 1024 ) / 10;
02780 CalcFasaCost_AddPrice(&total, "Power Amplifiers", power_amp);
02781 }
02782
02783
02784
02785
02786
02787 int turret_price = 5000 * (turret / 10) / 1024;
02788 CalcFasaCost_AddPrice(&total, "Turret", turret_price);
02789
02790
02791
02792
02793 if(MechMove(mech) == MOVE_HOVER
02794 || MechMove(mech) == MOVE_FOIL
02795 || MechMove(mech) == MOVE_SUB) {
02796 float lift_dive = 20000 * (0.1 * MechTons(mech));
02797 CalcFasaCost_AddPrice(&total, "Lift/Dive Equip", lift_dive);
02798 }
02799
02800 if(MechMove(mech) == MOVE_VTOL) {
02801 float vtol_eq = 40000 * (0.1 * MechTons(mech));
02802 CalcFasaCost_AddPrice(&total, "Rotor", vtol_eq);
02803 }
02804 }
02805
02806
02807
02808
02809
02810 if (MechType(mech) != CLASS_BSUIT) {
02811
02812
02813
02814 int engine_basecost = (MechSpecials(mech) & CE_TECH ? 10000 :
02815 MechSpecials(mech) & LE_TECH ? 15000 :
02816 MechSpecials(mech) & XL_TECH ? 20000 :
02817 MechSpecials(mech) & XXL_TECH ? 100000 :
02818 MechSpecials(mech) & ICE_TECH ? 1250 : 5000);
02819
02820 int engine_size = MechEngineSize(mech);
02821
02822 if (MechMove(mech) == MOVE_WHEEL ||
02823 MechMove(mech) == MOVE_FOIL ||
02824 MechMove(mech) == MOVE_HOVER ||
02825 MechMove(mech) == MOVE_HULL ||
02826 MechMove(mech) == MOVE_SUB ||
02827 MechMove(mech) == MOVE_VTOL) {
02828 engine_size = engine_size - susp_factor(mech);
02829 }
02830
02831 int engine_price = (engine_basecost * engine_size * MechTons(mech)) / 75;
02832
02833 CalcFasaCost_AddPrice(&total, "Engine", engine_price);
02834
02835
02836
02837
02838
02839
02840 int num_jjs = MechJumpSpeed(mech) * MP_PER_KPH;
02841 int jj_price = MechTons(mech) * pow(num_jjs, 2) * 200.0;
02842 if (num_jjs > 0)
02843 CalcFasaCost_AddPrice(&total, "Jumpjets", jj_price);
02844
02845
02846
02847
02848 int numsinks = MechRealNumsinks(mech);
02849
02850 int sinkcost;
02851 if(MechSpecials(mech) & DOUBLE_HEAT_TECH || MechSpecials(mech) & CLAN_TECH)
02852 sinkcost = 6000;
02853 else if(MechSpecials2(mech) & COMPACT_HS_TECH)
02854 sinkcost = 3000;
02855 else
02856 sinkcost = 2000;
02857
02858 if((MechSpecials(mech) & DOUBLE_HEAT_TECH || MechSpecials(mech) & CLAN_TECH)) {
02859
02860 numsinks = BOUNDED(0, numsinks/2, 500);
02861 }
02862
02863
02864 if(MechSpecials(mech) & DOUBLE_HEAT_TECH || MechSpecials(mech) & CLAN_TECH
02865 || MechSpecials2(mech) & COMPACT_HS_TECH || MechSpecials(mech) & ICE_TECH)
02866 CalcFasaCost_AddPrice(&total, "Heat Sinks", (numsinks * sinkcost));
02867 else {
02868 CalcFasaCost_AddPrice(&total, "Heat Sinks",
02869 (BOUNDED(0, numsinks - 10, 500) * sinkcost));
02870 }
02871
02872
02873 #if COST_DEBUG
02874 SendDebug(tprintf("Heat Sinks: %d, Cost Per Sink: %d", numsinks, sinkcost));
02875 #endif
02876
02877
02878 int total_armor = 0;
02879 int armor_section = 0;
02880 for(armor_section = 0; armor_section < NUM_SECTIONS; ++armor_section) {
02881 total_armor += GetSectOArmor(mech, armor_section);
02882 total_armor += GetSectORArmor(mech, armor_section);
02883 }
02884 float armor_tons = total_armor / 16.0;
02885
02886 int armor_cost_point = (MechSpecials(mech) & FF_TECH ? 20000 : MechSpecials2(mech) &
02887 STEALTH_ARMOR_TECH ? 50830 : MechSpecials(mech) &
02888 HARDA_TECH ? 15000 : MechSpecials2(mech) & LT_FF_ARMOR_TECH ?
02889 15000 : MechSpecials2(mech) & HVY_FF_ARMOR_TECH ? 25000 :
02890 10000);
02891 #if COST_DEBUG
02892 SendDebug(tprintf("Armor Tons %.1f(%d pts) * Armor Cost Per Point %d",
02893 armor_tons, total_armor, armor_cost_point));
02894 #endif
02895 int armor_price = armor_tons * armor_cost_point;
02896 CalcFasaCost_AddPrice(&total, "Armor", armor_price);
02897 }
02898
02899
02900 for(i = 0; i < NUM_SECTIONS; i++)
02901 for(ii = 0; ii < NUM_CRITICALS; ii++) {
02902 part = GetPartType(mech, i, ii);
02903 if(IsActuator(part) || part == EMPTY)
02904 continue;
02905 if(IsSpecial(part))
02906
02907 switch (Special2I(part)) {
02908 case LIFE_SUPPORT:
02909 continue;
02910 case SENSORS:
02911 continue;
02912 case COCKPIT:
02913 continue;
02914 case ENGINE:
02915 continue;
02916 case GYRO:
02917 continue;
02918 case HEAT_SINK:
02919 continue;
02920 case JUMP_JET:
02921 continue;
02922 case FERRO_FIBROUS:
02923 continue;
02924 case ENDO_STEEL:
02925 continue;
02926 case TRIPLE_STRENGTH_MYOMER:
02927 continue;
02928 case STEALTH_ARMOR:
02929 continue;
02930 #if 0
02931
02932 case HARDPOINT:
02933 continue;
02934 #endif
02935 default:
02936 break;
02937 }
02938 if(IsAmmo(part)) {
02939 part = FindAmmoType(mech, i, ii);
02940 int ammo_part_cost = GetPartCost(part) * GetPartData(mech,i,ii);
02941 CalcFasaCost_AddPrice(&total, (char*)part_name(part, 0),
02942 ammo_part_cost);
02943 } else {
02944
02945
02946 int indiv_part_cost = GetPartCost(part);
02947 if (MechType(mech) != CLASS_MECH && IsWeapon(part)) {
02948 indiv_part_cost *= MechWeapons[part-1].criticals;
02949
02950 }
02951 CalcFasaCost_AddPrice(&total, (char*)part_name(part, 0),
02952 indiv_part_cost);
02953 }
02954 }
02955
02956 if(MechType(mech) != CLASS_MECH && MechType(mech) != CLASS_BSUIT) {
02957 switch (MechMove(mech)) {
02958 case MOVE_TRACK:
02959 mod = (float) 1 + (float) ((float) MechTons(mech) / (float) 100);
02960 break;
02961 case MOVE_WHEEL:
02962 mod = (float) 1 + (float) ((float) MechTons(mech) / (float) 200);
02963 break;
02964 case MOVE_HOVER:
02965 mod = (float) 1 + (float) ((float) MechTons(mech) / (float) 50);
02966 break;
02967 case MOVE_VTOL:
02968 mod = (float) 1 + (float) ((float) MechTons(mech) / (float) 30);
02969 break;
02970 case MOVE_HULL:
02971 mod = (float) 1 + (float) ((float) MechTons(mech) / (float) 200);
02972 break;
02973 case MOVE_FOIL:
02974 mod = (float) 1 + (float) ((float) MechTons(mech) / (float) 75);
02975 break;
02976 case MOVE_SUB:
02977 mod = (float) 1 + (float) ((float) MechTons(mech) / (float) 50);
02978 break;
02979 }
02980 } else if (MechType(mech) == CLASS_BSUIT) {
02981
02982
02983 mod = 0.75;
02984 } else {
02985
02986 mod = (float) 1 + (float) ((float) MechTons(mech) / (float) 100);
02987 }
02988
02989 if (MechIsOmniMech(mech)) {
02990 SendDebug(tprintf("Mech is Omni, multiplying %lld by .25", total));
02991 total *= .25;
02992 }
02993
02994 #if COST_DEBUG
02995 SendDebug(tprintf("Price Total %.0f * Mod - %f = %.0f", total, mod, total*mod));
02996 #endif
02997
02998 return (total * mod);
02999 }
03000
03001 #endif
03002
03003 #ifdef BT_CALCULATE_BV
03004 int FindAverageGunnery(MECH * mech) {
03005 #if 1
03006
03007 return FindPilotGunnery(mech, 0);
03008 #else
03009 int runtot = 0;
03010 int i;
03011
03012 if(!mech)
03013 return 12;
03014
03015 for(i = 0; i < 5; i++) {
03016 runtot +=
03017 FindPilotGunnery(mech,
03018 (i == 0 ? 0 : i == 1 ? 4 : i ==
03019 2 ? 5 : i == 3 ? 6 : i == 4 ? 103 : 0));
03020 }
03021 return (runtot / 5);
03022 #endif
03023 }
03024
03025 #undef DEBUG_BV
03026 #define HIGH_SKILL 8
03027 #define LOW_SKILL 0
03028 float skillmul[HIGH_SKILL][HIGH_SKILL] = {
03029 {2.05, 2.00, 1.95, 1.90, 1.85, 1.80, 1.75, 1.70},
03030 {1.85, 1.80, 1.75, 1.70, 1.65, 1.60, 1.55, 1.50},
03031 {1.65, 1.60, 1.55, 1.50, 1.45, 1.40, 1.35, 1.30},
03032 {1.45, 1.40, 1.35, 1.30, 1.25, 1.20, 1.15, 1.10},
03033 {1.25, 1.20, 1.15, 1.10, 1.05, 1.00, 0.95, 0.90},
03034 {1.15, 1.10, 1.05, 1.00, 0.95, 0.90, 0.85, 0.80},
03035 {1.05, 1.00, 0.95, 0.90, 0.85, 0.80, 0.75, 0.70},
03036 {0.95, 0.90, 0.85, 0.80, 0.75, 0.70, 0.65, 0.60}
03037 };
03038
03039 #define LAZY_SKILLMUL(n) (n < LOW_SKILL ? LOW_SKILL : n >= HIGH_SKILL - 1 ? HIGH_SKILL - 1 : n)
03040
03041 int CalculateBV(MECH * mech, int gunstat, int pilstat) {
03042 int defbv = 0, offbv = 0, i, ii, temp, temp2, deduct =
03043 0, offweapbv = 0, defweapbv = 0, armor = 0, intern =
03044 0, weapindx, mostheat = 0, tempheat =
03045 0, mechspec, mechspec2, type, move, pilskl = pilstat, gunskl =
03046 gunstat;
03047 int debug1 = 0, debug2 = 0, debug3 = 0, debug4 = 0;
03048 float maxspeed, mul = 1.00;
03049
03050 if(!mech)
03051 return 0;
03052
03053 if(gunstat == 100 || pilstat == 100) {
03054 if(muxevent_tick - MechBVLast(mech) < 30)
03055 return MechBV(mech);
03056 else
03057 MechBVLast(mech) = muxevent_tick;
03058 }
03059
03060 type = MechType(mech);
03061 move = MechMove(mech);
03062 mechspec = MechSpecials(mech);
03063 mechspec2 = MechSpecials2(mech);
03064 if(gunstat == 100)
03065 pilskl = FindPilotPiloting(mech);
03066 if(pilstat == 100)
03067 gunskl = FindAverageGunnery(mech);
03068
03069 for(i = 0; i < NUM_SECTIONS; i++) {
03070 armor += (debug1 =
03071 GetSectArmor(mech,
03072 i) *
03073 (mechspec & HARDA_TECH ? 200 : 100));
03074 if(type == CLASS_MECH
03075 && (i == CTORSO || i == LTORSO || i == RTORSO)) {
03076 armor += (debug2 =
03077 GetSectRArmor(mech,
03078 i) *
03079 (mechspec & HARDA_TECH ? 200 : 100));
03080 #if 0
03081
03082 if(mechspec2 & TORSOCOCKPIT_TECH && i == CTORSO)
03083 armor += (debug4 =
03084 (((GetSectArmor(mech, i) +
03085 GetSectRArmor(mech,
03086 i)) * 2) *
03087 (mechspec & HARDA_TECH ? 200 : 100)));
03088 #endif
03089 }
03090 if(!is_aero(mech))
03091 intern += (debug3 =
03092 GetSectInt(mech,
03093 i) *
03094 (mechspec & COMPI_TECH ? 50 : mechspec &
03095 REINFI_TECH ? 200 : 100));
03096 else
03097 intern = (debug3 = AeroSI(mech));
03098 #ifdef DEBUG_BV
03099 SendDebug(tprintf
03100 ("Armoradd : %d ArmorRadd : %d Internadd : %d",
03101 debug1 / 100, debug2 / 100, debug3 / 100));
03102 if(mechspec2 & TORSOCOCKPIT_TECH && i == CTORSO)
03103 SendDebug(tprintf("TorsoCockpit Armoradd : %d", debug4));
03104 #endif
03105
03106 debug1 = debug2 = debug3 = debug4 = 0;
03107 for(ii = 0; ii < CritsInLoc(mech, i); ii++) {
03108 if(IsWeapon(temp = GetPartType(mech, i, ii))) {
03109 weapindx = (Weapon2I(temp));
03110 if(PartIsNonfunctional(mech, i, ii)) {
03111 if(type == CLASS_MECH)
03112 ii += (MechWeapons[weapindx].criticals - 1);
03113 continue;
03114 }
03115 if(MechWeapons[weapindx].special & AMS) {
03116 defweapbv += (debug1 =
03117 (MechWeapons[weapindx].battlevalue *
03118 100) * (float) (3000 /
03119 (MechWeapons
03120 [weapindx].vrt *
03121 100)));
03122
03123 #ifdef DEBUG_BV
03124 SendDebug(tprintf
03125 ("DefWeapBVadd (%s) : %d - Total : %d",
03126 MechWeapons[weapindx].name,
03127 debug1 / 100, defweapbv / 100));
03128 #endif
03129
03130 } else {
03131 offweapbv += (debug1 =
03132 (MechWeapons[weapindx].battlevalue *
03133 (GetPartFireMode(mech, i, ii) &
03134 REAR_MOUNT ? 50 : 100)) *
03135 (float) ((float) 3000 /
03136 (float) (MechWeapons
03137 [weapindx].vrt *
03138 100)));
03139 if(MechWeapons[weapindx].type == TMISSILE)
03140 if(FindArtemisForWeapon(mech, i, ii))
03141 offweapbv +=
03142 (MechWeapons[weapindx].battlevalue *
03143 20);
03144 #ifdef DEBUG_BV
03145 SendDebug(tprintf
03146 ("OffWeapBVadd (%s) : %d - Total : %d",
03147 MechWeapons[weapindx].name,
03148 debug1 / 100, offweapbv / 100));
03149 #endif
03150
03151 }
03152 if(type == CLASS_MECH) {
03153 if(!(GetPartFireMode(mech, i, ii) & REAR_MOUNT)) {
03154 tempheat =
03155 ((MechWeapons[weapindx].heat * 100) *
03156 (float) ((float) 3000 /
03157 (float) (MechWeapons[weapindx].
03158 vrt * 100)));
03159 if(MechWeapons[weapindx].special & ULTRA)
03160 tempheat = (tempheat * 2);
03161 if(MechWeapons[weapindx].special & STREAK)
03162 tempheat = (tempheat / 2);
03163 mostheat += tempheat;
03164 #ifdef DEBUG_BV
03165 SendDebug(tprintf
03166 ("Tempheatadded (%s) : %d - Total : %d",
03167 MechWeapons[weapindx].name,
03168 tempheat / 100, mostheat / 100));
03169 #endif
03170 tempheat = 0;
03171 }
03172 }
03173 if(type == CLASS_MECH)
03174 ii += (MechWeapons[weapindx].criticals - 1);
03175 } else if(IsAmmo(temp)) {
03176 if(PartIsNonfunctional(mech, i, ii)
03177 || !GetPartData(mech, i, ii))
03178 continue;
03179 #if 0
03180
03181 mul =
03182 ((temp2 =
03183 GetPartAmmoMode(mech, i,
03184 ii)) & AC_AP_MODE ? 4 : temp2 &
03185 AC_PRECISION_MODE ? 6 : temp2 & (TRACER_MODE |
03186 STINGER_MODE |
03187 SWARM_MODE |
03188 SWARM1_MODE |
03189 SGUIDED_MODE) ?
03190 1.5 : 1);
03191 #else
03192 mul =
03193 ((temp2 =
03194 GetPartAmmoMode(mech, i,
03195 ii)) & AC_AP_MODE ? 4 : temp2 &
03196 AC_PRECISION_MODE ? 6 : temp2 & (SWARM_MODE |
03197 SWARM1_MODE |
03198 STINGER_MODE) ?
03199 1.5 : 1);
03200 #endif
03201 mul =
03202 (mul *
03203 ((float)
03204 ((float) GetPartData(mech, i, ii) /
03205 (float) MechWeapons[weapindx =
03206 Ammo2WeaponI(temp)].
03207 ammoperton)));
03208
03209 #ifdef DEBUG_BV
03210 SendDebug(tprintf
03211 ("AmmoBVmul (%s) : %.2f",
03212 MechWeapons[weapindx].name, mul));
03213 #endif
03214
03215 if(MechWeapons[weapindx].special & AMS) {
03216 defweapbv += (debug1 =
03217 (((MechWeapons[weapindx].
03218 battlevalue / 10) * 100) * mul) *
03219 (float) ((float) 3000 /
03220 (float) (MechWeapons
03221 [weapindx].vrt *
03222 100)));
03223
03224 #ifdef DEBUG_BV
03225 SendDebug(tprintf
03226 ("AmmoDefWeapBVadd (%s) : %d - Total : %d",
03227 MechWeapons[weapindx].name,
03228 debug1 / 100, defweapbv / 100));
03229 #endif
03230
03231 } else {
03232
03233 #ifdef DEBUG_BV
03234 SendDebug(tprintf
03235 ("Abattlebalue (%s) : %d",
03236 MechWeapons[weapindx].name,
03237 (MechWeapons[weapindx].battlevalue /
03238 10)));
03239 #endif
03240
03241 offweapbv += (debug1 =
03242 (((MechWeapons[weapindx].
03243 battlevalue / 10) * 100) * mul) *
03244 (float) ((float) 3000 /
03245 (float) (MechWeapons
03246 [weapindx].vrt *
03247 100)));
03248
03249 #ifdef DEBUG_BV
03250 SendDebug(tprintf
03251 ("AmmoOffWeapBVadd (%s) : %d - Total : %d",
03252 MechWeapons[weapindx].name,
03253 debug1 / 100, offweapbv / 100));
03254 #endif
03255
03256 }
03257 }
03258 if((IsAmmo(temp)
03259 || (IsWeapon(temp)
03260 && MechWeapons[(Weapon2I(temp))].special & GAUSS))
03261 && type == CLASS_MECH) {
03262 if(mechspec & CLAN_TECH)
03263 if(i == CTORSO || i == HEAD || i == RLEG
03264 || i == LLEG) {
03265
03266 #ifdef DEBUG_BV
03267 SendDebug("20 deduct added for ammo");
03268 #endif
03269 deduct += 2000;
03270 continue;
03271 }
03272 if(mechspec &
03273 (XL_TECH | XXL_TECH | ICE_TECH | LE_TECH)) {
03274
03275 #ifdef DEBUG_BV
03276 SendDebug("20/2000 deduct added for ammo");
03277 #endif
03278
03279 deduct += 2000;
03280 continue;
03281 }
03282 if((i == CTORSO || i == RLEG || i == LLEG
03283 || i == HEAD)
03284 && !(MechSections(mech)[i].config & CASE_TECH)) {
03285
03286 #ifdef DEBUG_BV
03287 SendDebug("20 deduct added for ammo");
03288 #endif
03289
03290 deduct += 2000;
03291 continue;
03292 }
03293 if((i == RARM || i == LARM)
03294 && (!(MechSections(mech)[i].config & CASE_TECH)
03295 &&
03296 !(MechSections(mech)
03297 [(i ==
03298 RARM ? RTORSO : LTORSO)].
03299 config & CASE_TECH))) {
03300
03301 #ifdef DEBUG_BV
03302 SendDebug("20 deduct added for ammo");
03303 #endif
03304
03305 deduct += 2000;
03306 continue;
03307 }
03308 }
03309
03310 }
03311 }
03312 if(type == CLASS_MECH) {
03313 mostheat +=
03314 (MechJumpSpeed(mech) >
03315 0 ? MAX((MechJumpSpeed(mech) / MP1) * 100, 300) : 200);
03316 if(mechspec2 & (NULLSIGSYS_TECH | STEALTH_ARMOR_TECH))
03317 mostheat += 1000;
03318 if((temp = (mostheat - (MechActiveNumsinks(mech) * 100))) > 0) {
03319 deduct += temp * 5;
03320 #ifdef DEBUG_BV
03321 SendDebug(tprintf
03322 ("Deduct add for heat : %d", (temp * 5) / 100));
03323 #endif
03324 }
03325 }
03326 #ifdef DEBUG_BV
03327 SendDebug(tprintf("DeductTotal : %d", deduct / 100));
03328 #endif
03329
03330 if(mechspec & ECM_TECH)
03331 defweapbv += 6100;
03332
03333 if(mechspec & BEAGLE_PROBE_TECH) {
03334 if(mechspec & CLAN_TECH)
03335 offweapbv += 1200;
03336 else
03337 offweapbv += 1000;
03338 }
03339 #if 0
03340
03341 if(mechspec2 & HDGYRO_TECH)
03342 defweapbv += 3000;
03343 #endif
03344
03345 if(mechspec & (XL_TECH | XXL_TECH | LE_TECH)) {
03346 if(mechspec & (CLAN_TECH | LE_TECH))
03347 mul = 1.125;
03348 else
03349 mul = 0.75;
03350 } else if(mechspec & ICE_TECH
03351 || MechType(mech) == CLASS_VEH_GROUND
03352 || MechType(mech) == CLASS_VEH_NAVAL) {
03353 mul = 0.5;
03354 } else {
03355 mul = 1.5;
03356 }
03357
03358 #ifdef DEBUG_BV
03359 SendDebug(tprintf("InternMul : %.2f", mul));
03360 #endif
03361
03362 armor = (armor * (MechType(mech) == CLASS_MECH ? 2 : 1));
03363 intern = intern * mul;
03364 mul = 1.00;
03365
03366 #ifdef DEBUG_BV
03367 SendDebug(tprintf
03368 ("ArmorEnd : %d IntEnd : %d", armor / 100,
03369 intern / 100));
03370 #endif
03371
03372 maxspeed = MMaxSpeed(mech);
03373 if(mechspec & MASC_TECH || mechspec2 & SUPERCHARGER_TECH) {
03374 if(mechspec & MASC_TECH && mechspec2 & SUPERCHARGER_TECH)
03375 maxspeed = maxspeed * 2.5;
03376 else
03377 maxspeed = maxspeed * 1.5;
03378 }
03379 if(mechspec & TRIPLE_MYOMER_TECH)
03380 maxspeed = ((WalkingSpeed(maxspeed) + MP1) * 1.5);
03381
03382 if(maxspeed <= MP2) {
03383 mul = 1.0;
03384 } else if(maxspeed <= MP4) {
03385 mul = 1.1;
03386 } else if(maxspeed <= MP6) {
03387 mul = 1.2;
03388 } else if(maxspeed <= MP9) {
03389 mul = 1.3;
03390 } else if(maxspeed <= MP1 * 13) {
03391 mul = 1.4;
03392 } else if(maxspeed <= MP1 * 18) {
03393 mul = 1.5;
03394 } else if(maxspeed <= MP1 * 24) {
03395 mul = 1.6;
03396 } else {
03397 mul = 1.7;
03398 }
03399
03400 if(IsDS(mech))
03401 mul = 1.0;
03402 else if(is_aero(mech))
03403 mul = 1.1;
03404
03405 if(mechspec2 & (NULLSIGSYS_TECH | STEALTH_ARMOR_TECH))
03406 mul += 1.5;
03407 if(MechInfantrySpecials(mech) & DC_KAGE_STEALTH_TECH)
03408 mul += .75;
03409 if(MechInfantrySpecials(mech) & FWL_ACHILEUS_STEALTH_TECH)
03410 mul += 1.5;
03411 if(MechInfantrySpecials(mech) & CS_PURIFIER_STEALTH_TECH)
03412 mul += 2.0;
03413 if(MechInfantrySpecials(mech) & FC_INFILTRATOR_STEALTH_TECH)
03414 mul += .75;
03415 if(MechInfantrySpecials(mech) & FC_INFILTRATOR_STEALTH_TECH)
03416 mul += 2.0;
03417
03418 #ifdef DEBUG_BV
03419 SendDebug(tprintf("DefBVMul : %.2f", mul));
03420 #endif
03421
03422 defbv = (armor + intern + (MechTons(mech) * 100) + defweapbv);
03423
03424 #ifdef DEBUG_BV
03425 SendDebug(tprintf("DefBV Tonnage added : %d", MechTons(mech)));
03426 #endif
03427
03428 if((defbv - deduct) < 1)
03429 defbv = 1;
03430 else
03431 defbv -= deduct;
03432 if(type != CLASS_MECH)
03433 defbv =
03434 ((defbv *
03435 (move == MOVE_TRACK ? 0.8 : move ==
03436 MOVE_WHEEL ? 0.7 : move == MOVE_HOVER ? 0.6 : move ==
03437 MOVE_VTOL ? 0.4 : move == MOVE_FOIL || move == MOVE_SUB
03438 || move == MOVE_HULL ? 0.5 : 1.0)) - deduct);
03439 defbv = defbv * mul;
03440
03441 #ifdef DEBUG_BV
03442 SendDebug(tprintf("DefBV : %d", defbv / 100));
03443 #endif
03444
03445 if((type == CLASS_MECH || is_aero(mech))
03446 && mostheat > (MechActiveNumsinks(mech) * 100)) {
03447 #ifdef DEBUG_BV
03448 SendDebug(tprintf
03449 ("Pre-Heat OffWeapBV : %d", offweapbv / 100));
03450 #endif
03451 i = (((MechActiveNumsinks(mech) / 100) * offweapbv) /
03452 mostheat);
03453 ii = ((offweapbv - i) / 2);
03454 offweapbv = i + ii;
03455
03456 #ifdef DEBUG_BV
03457 SendDebug(tprintf
03458 ("Post-Heat OffWeapBV : %d", offweapbv / 100));
03459 #endif
03460 }
03461
03462
03463
03464 mul =
03465 pow((((((IsDS(mech) ? WalkingSpeed(MMaxSpeed(mech)) :
03466 MMaxSpeed(mech)) / MP1) +
03467 (mechspec & MASC_TECH ? 1 : 0) +
03468 (mechspec & TRIPLE_MYOMER_TECH ? 1 : 0) +
03469 (mechspec2 & SUPERCHARGER_TECH ? 1 : 0) - 5) / 10) +
03470 1), 1.2);
03471
03472 #ifdef DEBUG_BV
03473 SendDebug(tprintf("DumbMul : %.2f", mul));
03474 #endif
03475
03476 if(mechspec2 & OMNIMECH_TECH)
03477 mul += .3;
03478
03479 offweapbv = offweapbv * mul;
03480 if(type != CLASS_AERO && type != CLASS_DS
03481 && MechJumpSpeed(mech) > 0)
03482 offweapbv +=
03483 ((MechJumpSpeed(mech) / MP1) *
03484 (100 * (MechTons(mech) / 5)));
03485 offbv = offweapbv;
03486
03487 #ifdef DEBUG_BV
03488 SendDebug(tprintf("OffWeapBVAfter : %d", offweapbv / 100));
03489 SendDebug(tprintf
03490 ("DefBV : %d OffBV : %d TotalBV : %d", defbv / 100,
03491 offbv / 100, (offbv + defbv) / 100));
03492 #endif
03493
03494 mul = (skillmul[LAZY_SKILLMUL(gunskl)][LAZY_SKILLMUL(pilskl)]);
03495
03496 #ifdef DEBUG_BV
03497 SendDebug(tprintf
03498 ("SkillMul : %.2f (%d/%d)", mul, gunskl, pilskl));
03499 #endif
03500 return ((offbv + defbv) / 100) * mul;
03501 }
03502 #endif
03503
03504 int MechFullNoRecycle(MECH * mech, int num) {
03505 int i;
03506
03507 for(i = 0; i < NUM_SECTIONS; i++) {
03508 if(num & CHECK_WEAPS && SectHasBusyWeap(mech, i))
03509 return 1;
03510 if(num & CHECK_PHYS && MechSections(mech)[i].recycle > 0)
03511 return 2;
03512 }
03513 return 0;
03514 }
03515
03516 #ifdef BT_COMPLEXREPAIRS
03517 int GetPartMod(MECH * mech, int t) {
03518 int val, div, bound;
03519
03520 div = (t && t == Special(GYRO) ? 100 : t
03521 && t == Special(ENGINE) ? 20 : 10);
03522 bound = (t && t == Special(GYRO) ? 3 : t
03523 && t == Special(ENGINE) ? 19 : 9);
03524 val = (t
03525 && (t == Special(GYRO)
03526 || t ==
03527 Special(ENGINE)) ? MechEngineSize(mech) :
03528 MechTons(mech));
03529
03530 if(val % div != 0)
03531 val = val + (div - (val % div));
03532
03533 return BOUNDED(0, (val / div) - 1, bound);
03534 }
03535
03536 int ProperArmor(MECH * mech) {
03537
03538 return Cargo(MechSpecials(mech) & FF_TECH ? FF_ARMOR :
03539 MechSpecials(mech) & HARDA_TECH ? HD_ARMOR :
03540 MechSpecials2(mech) & HVY_FF_ARMOR_TECH ?
03541 HVY_FF_ARMOR : MechSpecials2(mech) & LT_FF_ARMOR_TECH
03542 ? LT_FF_ARMOR : MechSpecials2(mech) &
03543 STEALTH_ARMOR_TECH ? STH_ARMOR : S_ARMOR);
03544 }
03545
03546 int ProperInternal(MECH * mech) {
03547 int part = 0;
03548
03549 if(mudconf.btech_complexrepair) {
03550 part = (MechSpecials(mech) & ES_TECH ? TON_ESINTERNAL_FIRST :
03551 MechSpecials(mech) & REINFI_TECH ?
03552 TON_REINTERNAL_FIRST : MechSpecials(mech) & COMPI_TECH
03553 ? TON_COINTERNAL_FIRST : TON_INTERNAL_FIRST);
03554 part += GetPartMod(mech, 0);
03555 } else {
03556 part = (MechSpecials(mech) & ES_TECH ? ES_INTERNAL :
03557 MechSpecials(mech) & REINFI_TECH ? RE_INTERNAL :
03558 MechSpecials(mech) & COMPI_TECH ? CO_INTERNAL :
03559 S_INTERNAL);
03560 }
03561 return Cargo(part);
03562 }
03563
03564 int alias_part(MECH * mech, int t, int loc) {
03565 int part = 0;
03566
03567 if(!IsSpecial(t))
03568 return t;
03569
03570 if(mudconf.btech_complexrepair) {
03571 int tonmod = GetPartMod(mech, t);
03572 int locmod;
03573 if(MechIsQuad(mech))
03574 locmod = (loc == RARM || loc == LARM || loc == RLEG
03575 || loc == LLEG ? 2 : 0);
03576 else
03577 locmod = (loc == RARM || loc == LARM ? 1 : loc == LLEG
03578 || loc == RLEG ? 2 : 0);
03579
03580 part = (locmod
03581 && (t == Special(SHOULDER_OR_HIP)
03582 || t == Special(UPPER_ACTUATOR)) ? (locmod ==
03583 1 ?
03584 Cargo
03585 (TON_ARMUPPER_FIRST
03586 +
03587 tonmod) :
03588 Cargo
03589 (TON_LEGUPPER_FIRST
03590 +
03591 tonmod)) :
03592 locmod
03593 && t == Special(LOWER_ACTUATOR) ? (locmod ==
03594 1 ?
03595 Cargo
03596 (TON_ARMLOWER_FIRST
03597 +
03598 tonmod) :
03599 Cargo
03600 (TON_LEGLOWER_FIRST
03601 +
03602 tonmod)) : locmod
03603 && t == Special(HAND_OR_FOOT_ACTUATOR) ? (locmod ==
03604 1 ?
03605 Cargo
03606 (TON_ARMHAND_FIRST
03607 +
03608 tonmod) :
03609 Cargo
03610 (TON_LEGFOOT_FIRST
03611 +
03612 tonmod)) :
03613 t == Special(ENGINE)
03614 && MechSpecials(mech) & XL_TECH ?
03615 Cargo(TON_ENGINE_XL_FIRST + tonmod) : t ==
03616 Special(ENGINE)
03617 && MechSpecials(mech) & ICE_TECH ?
03618 Cargo(TON_ENGINE_ICE_FIRST + tonmod) : t ==
03619 Special(ENGINE)
03620 && MechSpecials(mech) & CE_TECH ?
03621 Cargo(TON_ENGINE_COMP_FIRST + tonmod) : t ==
03622 Special(ENGINE)
03623 && MechSpecials(mech) & XXL_TECH ?
03624 Cargo(TON_ENGINE_XXL_FIRST + tonmod) : t ==
03625 Special(ENGINE)
03626 && MechSpecials(mech) & LE_TECH ?
03627 Cargo(TON_ENGINE_LIGHT_FIRST + tonmod) : t ==
03628 Special(ENGINE) ? Cargo(TON_ENGINE_FIRST +
03629 tonmod) : t ==
03630 Special(HEAT_SINK)
03631 && MechSpecials(mech) & (DOUBLE_HEAT_TECH | CLAN_TECH)
03632 ? Cargo(DOUBLE_HEAT_SINK) : t == Special(HEAT_SINK)
03633 && MechSpecials2(mech) & COMPACT_HS_TECH ?
03634 Cargo(COMPACT_HEAT_SINK) : t == Special(GYRO)
03635 && MechSpecials2(mech) & XLGYRO_TECH ?
03636 Cargo(TON_XLGYRO_FIRST + tonmod) : t == Special(GYRO)
03637 && MechSpecials2(mech) & HDGYRO_TECH ?
03638 Cargo(TON_HDGYRO_FIRST + tonmod) : t == Special(GYRO)
03639 && MechSpecials2(mech) & CGYRO_TECH ?
03640 Cargo(TON_CGYRO_FIRST + tonmod) : t ==
03641 Special(GYRO) ? Cargo(TON_GYRO_FIRST + tonmod) : t ==
03642 Special(SENSORS) ? Cargo(TON_SENSORS_FIRST +
03643 tonmod) : t ==
03644 Special(JUMP_JET) ? Cargo(TON_JUMPJET_FIRST +
03645 tonmod) : t);
03646 } else {
03647 part = (IsActuator(t) ? Cargo(S_ACTUATOR) :
03648 t == Special(ENGINE)
03649 && MechSpecials(mech) & XL_TECH ? Cargo(XL_ENGINE) : t
03650 == Special(ENGINE)
03651 && MechSpecials(mech) & ICE_TECH ? Cargo(IC_ENGINE) :
03652 t == Special(ENGINE)
03653 && MechSpecials(mech) & CE_TECH ? Cargo(COMP_ENGINE) :
03654 t == Special(ENGINE)
03655 && MechSpecials(mech) & XXL_TECH ? Cargo(XXL_ENGINE) :
03656 t == Special(ENGINE)
03657 && MechSpecials(mech) & LE_TECH ? Cargo(LIGHT_ENGINE)
03658 : t == Special(HEAT_SINK)
03659 && MechSpecials(mech) & (DOUBLE_HEAT_TECH | CLAN_TECH)
03660 ? Cargo(DOUBLE_HEAT_SINK) : t == Special(HEAT_SINK)
03661 && MechSpecials2(mech) & COMPACT_HS_TECH ?
03662 Cargo(COMPACT_HEAT_SINK) : t == Special(GYRO)
03663 && MechSpecials2(mech) & XLGYRO_TECH ? Cargo(XL_GYRO)
03664 : t == Special(GYRO)
03665 && MechSpecials2(mech) & HDGYRO_TECH ? Cargo(HD_GYRO)
03666 : t == Special(GYRO)
03667 && MechSpecials2(mech) & CGYRO_TECH ? Cargo(COMP_GYRO)
03668 : t);
03669 }
03670 return part;
03671 }
03672
03673 int ProperMyomer(MECH * mech) {
03674 int part;
03675
03676 part =
03677 (MechSpecials(mech) & TRIPLE_MYOMER_TECH ?
03678 TON_TRIPLEMYOMER_FIRST : TON_MYOMER_FIRST);
03679 part += GetPartMod(mech, 0);
03680
03681 return Cargo(part);
03682 }
03683 #endif
03684
03685
03686
03687 int HeatFactor(MECH * mech) {
03688
03689 int factor = 0;
03690 char buf[LBUF_SIZE];
03691
03692 if(MechType(mech) != CLASS_MECH) {
03693 factor = (((MechSpecials(mech) & ICE_TECH)) ? -1 : 21);
03694 return factor;
03695 } else {
03696 factor =
03697 (MechPlusHeat(mech) +
03698 (2 * (MechPlusHeat(mech) - MechMinusHeat(mech))));
03699 return ((NullSigSysActive(mech) || HasWorkingECMSuite(mech)
03700 || StealthArmorActive(mech)) ? -1 : factor);
03701 }
03702 snprintf(buf, LBUF_SIZE,
03703 "HeatFactor : Invalid heat factor calculation on #%d.",
03704 mech->mynum);
03705 SendDebug(buf);
03706 }
03707
03708
03709
03710
03711
03712
03713
03714 int WeaponIsNonfunctional(MECH * mech, int section, int crit,
03715 int numcrits) {
03716 int sum = 0, disabled = 0, dested = 0;
03717
03718 if(numcrits <= 0)
03719 numcrits =
03720 GetWeaponCrits(mech,
03721 Weapon2I(GetPartType
03722 (mech, section, crit)));
03723
03724 while (sum < numcrits) {
03725 if(PartIsDestroyed(mech, section, crit + sum))
03726 dested++;
03727 else if(PartIsDisabled(mech, section, crit + sum))
03728 disabled++;
03729 sum++;
03730 }
03731
03732 if(disabled > 0)
03733 return 1;
03734
03735 if((numcrits == 1 && (dested || disabled)) ||
03736 (numcrits > 1 && (dested + disabled) >= numcrits / 2))
03737 return 2;
03738
03739 if(dested)
03740 return 0 - (dested + disabled);
03741
03742 return 0;
03743 }