src/hcode/btech/mech.c3.misc.c

Go to the documentation of this file.
00001 /*
00002  * Author: Cord Awtry <kipsta@mediaone.net>
00003  *  Copyright (c) 2000-2002 Cord Awtry
00004  *       All rights reserved
00005  *
00006  * Based on work that was:
00007  *  Copyright (c) 1997 Markus Stenberg
00008  *  Copyright (c) 1998-2000 Thomas Wouters
00009  */
00010 
00011 #include "mech.h"
00012 #include "p.mech.c3.misc.h"
00013 #include "p.mech.c3.h"
00014 #include "p.mech.c3i.h"
00015 #include "p.mech.utils.h"
00016 #include "p.mech.los.h"
00017 #include "p.mech.contacts.h"
00018 
00019 #define TARG_LOS_NONE 0
00020 #define TARG_LOS_CLEAR 1
00021 #define TARG_LOS_SOMETHING 2
00022 
00023 #define DEBUG_C3 0
00024 
00025 MECH *getMechInTempNetwork(int wIdx, dbref * myNetwork, int networkSize)
00026 {
00027         MECH *tempMech;
00028         dbref refOtherMech;
00029 
00030         if((wIdx > networkSize) || (wIdx < 0))
00031                 return NULL;
00032 
00033         refOtherMech = myNetwork[wIdx];
00034 
00035         if(refOtherMech > 0) {
00036                 tempMech = getMech(refOtherMech);
00037 
00038                 if(!tempMech)
00039                         return NULL;
00040 
00041                 if(Destroyed(tempMech))
00042                         return NULL;
00043 
00044                 return tempMech;
00045         }
00046 
00047         return NULL;
00048 }
00049 
00050 MECH *getOtherMechInNetwork(MECH * mech, int wIdx, int tCheckECM,
00051                                                         int tCheckStarted, int tCheckUncon, int tIsC3)
00052 {
00053         MECH *tempMech;
00054         dbref refOtherMech;
00055         int networkSize;
00056 
00057         networkSize =
00058                 (tIsC3 ? MechC3NetworkSize(mech) : MechC3iNetworkSize(mech));
00059 
00060         if((wIdx >= networkSize) || (wIdx < 0))
00061                 return NULL;
00062 
00063         refOtherMech =
00064                 (tIsC3 ? MechC3NetworkElem(mech, wIdx) : MechC3iNetworkElem(mech,
00065                                                                                                                                         wIdx));
00066 
00067         if(refOtherMech > 0) {
00068                 tempMech = getMech(refOtherMech);
00069 
00070                 if(!tempMech)
00071                         return NULL;
00072 
00073                 if(MechTeam(tempMech) != MechTeam(mech))
00074                         return NULL;
00075 
00076                 if(tempMech->mapindex != mech->mapindex)
00077                         return NULL;
00078 
00079                 if(Destroyed(tempMech))
00080                         return NULL;
00081 
00082                 if(tIsC3) {
00083                         if(!HasC3(tempMech))    /* Sanity check */
00084                                 return NULL;
00085 
00086                         if(C3Destroyed(tempMech))
00087                                 return NULL;
00088                 } else {
00089                         if(!HasC3i(tempMech))   /* Sanity check */
00090                                 return NULL;
00091 
00092                         if(C3iDestroyed(tempMech))
00093                                 return NULL;
00094                 }
00095 
00096                 if(tCheckECM)
00097                         if(AnyECMDisturbed(tempMech))
00098                                 return NULL;
00099 
00100                 if(tCheckStarted)
00101                         if(!Started(tempMech))
00102                                 return NULL;
00103 
00104                 if(tCheckUncon)
00105                         if(Uncon(tempMech))
00106                                 return NULL;
00107 
00108                 return tempMech;
00109         }
00110 
00111         return NULL;
00112 }
00113 
00114 void buildTempNetwork(MECH * mech, dbref * myNetwork, int *networkSize,
00115                                           int tCheckECM, int tCheckStarted, int tCheckUncon,
00116                                           int tIsC3)
00117 {
00118         int tempNetworkSize = 0;
00119         int baseNetworkSize;
00120         MECH *otherMech;
00121         dbref myTempNetwork[C3_NETWORK_SIZE];
00122         int i;
00123 
00124         /* Re-init the network */
00125         for(i = 0; i < C3_NETWORK_SIZE; i++)
00126                 myNetwork[i] = -1;
00127 
00128         *networkSize = 0;
00129 
00130         baseNetworkSize =
00131                 (tIsC3 ? MechC3NetworkSize(mech) : MechC3iNetworkSize(mech));
00132 
00133         if(baseNetworkSize == 0)
00134                 return;
00135 
00136         /*
00137          * Build the base netork of all the mechs that fit the criteria we passed in
00138          */
00139         for(i = 0; i < baseNetworkSize; i++) {
00140                 otherMech =
00141                         getOtherMechInNetwork(mech, i, tCheckECM, tCheckStarted,
00142                                                                   tCheckUncon, tIsC3);
00143 
00144                 if(!otherMech)
00145                         continue;
00146 
00147                 if(!Good_obj(otherMech->mynum))
00148                         continue;
00149 
00150                 myTempNetwork[tempNetworkSize] = otherMech->mynum;
00151                 tempNetworkSize++;
00152         }
00153 
00154         /*
00155          * Once we're here, we're done with the C3i stuff, but we need to make sure that this is a valid C3 network
00156          * still. For example, we may have lost a master due to death or something else, so we need to make sure we
00157          * have enough masters left to actually do something.
00158          *
00159          * A valid network is one where there are MIN((((NUM_MASTERS * 4) - NUM_MASTERS) + ((MY_MASTERS * 4) - MY_MASTERS), 11) units in the network
00160          */
00161         if(tIsC3) {
00162                 if(tempNetworkSize > 0)
00163                         tempNetworkSize =
00164                                 trimC3Network(mech, myTempNetwork, tempNetworkSize);
00165         }
00166 
00167         for(i = 0; i < tempNetworkSize; i++)
00168                 myNetwork[i] = myTempNetwork[i];
00169 
00170         *networkSize = tempNetworkSize;
00171 }
00172 
00173 void sendNetworkMessage(dbref player, MECH * mech, char *msg, int tIsC3)
00174 {
00175         int i;
00176         MECH *otherMech;
00177         const char *c = GetMechID(mech);
00178         char buf[LBUF_SIZE];
00179         int networkSize;
00180         dbref myNetwork[C3_NETWORK_SIZE];
00181 
00182         buildTempNetwork(mech, myNetwork, &networkSize, 1, 1, 1, tIsC3);
00183 
00184         for(i = 0; i < networkSize; i++) {
00185                 otherMech = getMechInTempNetwork(i, myNetwork, networkSize);
00186 
00187                 if(!otherMech)
00188                         continue;
00189 
00190                 if(!Good_obj(otherMech->mynum))
00191                         continue;
00192 
00193                 sprintf(buf, "%%ch%s/%s: %s%%cn", (tIsC3 ? "C3" : "C3i"), c, msg);
00194                 mech_notify(otherMech, MECHALL, buf);
00195         }
00196 
00197         sprintf(buf, "%%ch%s/You: %s%%cn", (tIsC3 ? "C3" : "C3i"), msg);
00198         mech_notify(mech, MECHALL, buf);
00199 }
00200 
00201 void showNetworkTargets(dbref player, MECH * mech, int tIsC3)
00202 {
00203         MAP *objMap = getMap(mech->mapindex);
00204         int i, j, wTemp, bearing;
00205         MECH *otherMech;
00206         float realRange, c3Range;
00207         char buff[100];
00208         char *mech_name;
00209         char move_type[30];
00210         char cStatus1, cStatus2, cStatus3, cStatus4, cStatus5;
00211         char weaponarc;
00212         int losFlag;
00213         int arc;
00214         int wSeeTarget = TARG_LOS_NONE;
00215         int wC3SeeTarget = TARG_LOS_NONE;
00216         int tShowStatusInfo = 0;
00217         char bufflist[MAX_MECHS_PER_MAP][120];
00218         float rangelist[MAX_MECHS_PER_MAP];
00219         int buffindex = 0;
00220         int sbuff[MAX_MECHS_PER_MAP];
00221         int networkSize;
00222         dbref myNetwork[C3_NETWORK_SIZE];
00223         dbref c3Ref;
00224 
00225         buildTempNetwork(mech, myNetwork, &networkSize, 1, 1, 0, tIsC3);
00226 
00227         /*
00228          * Send then a 'contacts' style report. This is different from the
00229          * normal contacts since it has a 'physical' range in it too.
00230          */
00231         notify_printf(player, "%s Contacts:", tIsC3 ? "C3" : "C3i");
00232 
00233         for(i = 0; i < objMap->first_free; i++) {
00234                 if(!(objMap->mechsOnMap[i] != mech->mynum &&
00235                          objMap->mechsOnMap[i] != -1))
00236                         continue;
00237 
00238                 otherMech = (MECH *) FindObjectsData(objMap->mechsOnMap[i]);
00239 
00240                 if(!otherMech)
00241                         continue;
00242 
00243                 if(!Good_obj(otherMech->mynum))
00244                         continue;
00245 
00246                 tShowStatusInfo = 0;
00247                 realRange = FlMechRange(objMap, mech, otherMech);
00248                 losFlag =
00249                         InLineOfSight(mech, otherMech, MechX(otherMech),
00250                                                   MechY(otherMech), realRange);
00251 
00252                 /*
00253                  * If we do see them, let's make sure it's not just a 'something'
00254                  */
00255                 if(losFlag) {
00256                         if(InLineOfSight_NB(mech, otherMech, MechX(otherMech),
00257                                                                 MechY(otherMech), 0.0))
00258                                 wSeeTarget = TARG_LOS_CLEAR;
00259                         else
00260                                 wSeeTarget = TARG_LOS_SOMETHING;
00261                 } else
00262                         wSeeTarget = TARG_LOS_NONE;
00263 
00264                 /*
00265                  * If I don't see it, let's see if someone else in the network does
00266                  */
00267                 if(wSeeTarget != TARG_LOS_CLEAR)
00268                         wC3SeeTarget = mechSeenByNetwork(mech, otherMech, tIsC3);
00269 
00270                 /* If noone sees it, we continue */
00271                 if(!wSeeTarget && !wC3SeeTarget)
00272                         continue;
00273 
00274                 /* Get our network range */
00275                 c3Range =
00276                         findC3RangeWithNetwork(mech, otherMech, realRange, myNetwork,
00277                                                                    networkSize, &c3Ref);
00278 
00279                 /* Figure out if we show the info or not... ie, do we actually 'see' it */
00280                 if((wSeeTarget != TARG_LOS_CLEAR) && (wC3SeeTarget != TARG_LOS_CLEAR)) {
00281                         tShowStatusInfo = 0;
00282                         mech_name = "something";
00283                 } else {
00284                         tShowStatusInfo = 1;
00285                         mech_name = silly_atr_get(otherMech->mynum, A_MECHNAME);
00286                 }
00287 
00288                 bearing =
00289                         FindBearing(MechFX(mech), MechFY(mech), MechFX(otherMech),
00290                                                 MechFY(otherMech));
00291                 strcpy(move_type, GetMoveTypeID(MechMove(otherMech)));
00292 
00293                 /* Get our weapon arc */
00294                 arc = InWeaponArc(mech, MechFX(otherMech), MechFY(otherMech));
00295                 weaponarc = getWeaponArc(mech, arc);
00296 
00297                 /* Now get our status chars */
00298                 if(!tShowStatusInfo) {
00299                         cStatus1 = ' ';
00300                         cStatus2 = ' ';
00301                         cStatus3 = ' ';
00302                         cStatus4 = ' ';
00303                         cStatus5 = ' ';
00304                 } else {
00305                         cStatus1 = getStatusChar(mech, otherMech, 1);
00306                         cStatus2 = getStatusChar(mech, otherMech, 2);
00307                         cStatus3 = getStatusChar(mech, otherMech, 3);
00308                         cStatus4 = getStatusChar(mech, otherMech, 4);
00309                         cStatus5 = getStatusChar(mech, otherMech, 5);
00310                 }
00311 
00312                 /* Now, build the string */
00313                 sprintf(buff,
00314                                 "%s%c%c%c[%s]%c %-11.11s x:%3d y:%3d z:%3d r:%4.1f c:%4.1f b:%3d s:%5.1f h:%3d S:%c%c%c%c%c%s",
00315                                 otherMech->mynum == MechTarget(mech) ? "%ch%cr" :
00316                                 (tShowStatusInfo &&
00317                                  !MechSeemsFriend(mech, otherMech)) ? "%ch%cy" : "",
00318                                 (losFlag & MECHLOSFLAG_SEESP) ? 'P' : ' ',
00319                                 (losFlag & MECHLOSFLAG_SEESS) ? 'S' : ' ', weaponarc,
00320                                 MechIDS(otherMech, MechSeemsFriend(mech, otherMech) ||
00321                                                 !tShowStatusInfo), move_type[0], mech_name,
00322                                 MechX(otherMech), MechY(otherMech), MechZ(otherMech),
00323                                 realRange, c3Range, bearing, MechSpeed(otherMech),
00324                                 MechVFacing(otherMech), cStatus1, cStatus2, cStatus3,
00325                                 cStatus4, cStatus5, (otherMech->mynum == MechTarget(mech)
00326                                                                          || !MechSeemsFriend(mech,
00327                                                                                                                  otherMech)) ? "%c" :
00328                                 "");
00329 
00330                 rangelist[buffindex] = realRange;
00331                 rangelist[buffindex] +=
00332                         (MechStatus(otherMech) & DESTROYED) ? 10000 : 0;
00333                 strcpy(bufflist[buffindex++], buff);
00334         }
00335 
00336         for(i = 0; i < buffindex; i++)
00337                 sbuff[i] = i;
00338 
00339         /* print a sorted list of detected mechs */
00340         /* use the ever-popular bubble sort */
00341         for(i = 0; i < (buffindex - 1); i++)
00342                 for(j = (i + 1); j < buffindex; j++)
00343                         if(rangelist[sbuff[j]] > rangelist[sbuff[i]]) {
00344                                 wTemp = sbuff[i];
00345                                 sbuff[i] = sbuff[j];
00346                                 sbuff[j] = wTemp;
00347                         }
00348 
00349         for(i = 0; i < buffindex; i++)
00350                 notify(player, bufflist[sbuff[i]]);
00351 
00352         notify_printf(player, "End %s Contact List", tIsC3 ? "C3" : "C3i");
00353 }
00354 
00355 void showNetworkData(dbref player, MECH * mech, int tIsC3)
00356 {
00357         int i, bearing;
00358         MECH *otherMech;
00359         float range;
00360         char buff[100];
00361         char *mech_name;
00362         char move_type[30];
00363         int networkSize;
00364         dbref myNetwork[C3_NETWORK_SIZE];
00365 
00366         notify_printf(player, "%s Network Status:", tIsC3 ? "C3" : "C3i");
00367 
00368         buildTempNetwork(mech, myNetwork, &networkSize, 1, 1, 0, tIsC3);
00369 
00370         for(i = 0; i < networkSize; i++) {
00371                 otherMech = getMechInTempNetwork(i, myNetwork, networkSize);
00372 
00373                 if(!otherMech)
00374                         continue;
00375 
00376                 if(!Good_obj(otherMech->mynum))
00377                         continue;
00378 
00379                 range = FlMechRange(objMap, mech, otherMech);
00380                 bearing =
00381                         FindBearing(MechFX(mech), MechFY(mech), MechFX(otherMech),
00382                                                 MechFY(otherMech));
00383 
00384                 strcpy(move_type, GetMoveTypeID(MechMove(otherMech)));
00385 
00386                 mech_name = silly_atr_get(otherMech->mynum, A_MECHNAME);
00387 
00388                 sprintf(buff,
00389                                 "%%ch%%cy[%s]%c %-12.12s x:%3d y:%3d z:%3d r:%4.1f b:%3d s:%5.1f h:%3d a: %3d i: %3d%%cn",
00390                                 MechIDS(otherMech, 1), move_type[0], mech_name,
00391                                 MechX(otherMech), MechY(otherMech), MechZ(otherMech), range,
00392                                 bearing, MechSpeed(otherMech), MechVFacing(otherMech),
00393                                 getRemainingArmorPercent(otherMech),
00394                                 getRemainingInternalPercent(otherMech));
00395 
00396                 notify(player, buff);
00397 
00398         }
00399 
00400         notify_printf(player, "End %s Network Status", tIsC3 ? "C3" : "C3i");
00401 }
00402 
00403 int mechSeenByNetwork(MECH * mech, MECH * mechTarget, int tIsC3)
00404 {
00405         int los = TARG_LOS_NONE;
00406         float range = 0.0;
00407         int i;
00408         int networkSize;
00409         dbref myNetwork[C3_NETWORK_SIZE];
00410         MECH *otherMech;
00411 
00412         buildTempNetwork(mech, myNetwork, &networkSize, 1, 1, 0, tIsC3);
00413 
00414         if(networkSize == 0)
00415                 return TARG_LOS_NONE;
00416 
00417         for(i = 0; i < networkSize; i++) {
00418                 otherMech = getMechInTempNetwork(i, myNetwork, networkSize);
00419 
00420                 if(!otherMech)
00421                         continue;
00422 
00423                 if(!Good_obj(otherMech->mynum))
00424                         continue;
00425 
00426                 if(otherMech == mechTarget)
00427                         continue;
00428 
00429                 range = FaMechRange(otherMech, mechTarget);
00430                 los =
00431                         InLineOfSight(otherMech, mechTarget, MechX(mechTarget),
00432                                                   MechY(mechTarget), range);
00433 
00434                 if(los) {
00435                         if(!InLineOfSight_NB(otherMech, mechTarget, MechX(mechTarget),
00436                                                                  MechY(mechTarget), range))
00437                                 los = TARG_LOS_SOMETHING;
00438                         else {
00439                                 los = TARG_LOS_CLEAR;
00440                                 break;
00441                         }
00442                 }
00443         }
00444 
00445         return los;
00446 }
00447 
00448 float findC3Range(MECH * mech, MECH * mechTarget, float realRange,
00449                                   dbref * c3Ref, int tIsC3)
00450 {
00451         int networkSize;
00452         dbref myNetwork[C3_NETWORK_SIZE];
00453 
00454         if(tIsC3) {
00455                 if(C3Destroyed(mech)) {
00456                         return realRange;
00457                 }
00458         } else {
00459                 if(C3iDestroyed(mech)) {
00460                         validateC3iNetwork(mech);
00461 
00462                         return realRange;
00463                 }
00464         }
00465 
00466         if(AnyECMDisturbed(mech))
00467                 return realRange;
00468 
00469         buildTempNetwork(mech, myNetwork, &networkSize, 1, 1, 0, tIsC3);
00470 
00471         return findC3RangeWithNetwork(mech, mechTarget, realRange, myNetwork,
00472                                                                   networkSize, c3Ref);
00473 }
00474 
00475 float findC3RangeWithNetwork(MECH * mech, MECH * mechTarget,
00476                                                          float realRange, dbref * myNetwork,
00477                                                          int networkSize, dbref * c3Ref)
00478 {
00479         float c3Range = 0.0;
00480         float bestRange = 0.0;
00481         int i;
00482         int inLOS = 0;
00483         int mapX, mapY;
00484         float hexX, hexY, hexZ;
00485         MECH *otherMech;
00486         MAP *map;
00487 
00488         bestRange = realRange;
00489         *c3Ref = 0;
00490 
00491         if(networkSize == 0)
00492                 return realRange;
00493 
00494         for(i = 0; i < networkSize; i++) {
00495                 otherMech = getMechInTempNetwork(i, myNetwork, networkSize);
00496 
00497                 if(!otherMech)
00498                         continue;
00499 
00500                 if(!Good_obj(otherMech->mynum))
00501                         continue;
00502 
00503                 if(mechTarget) {
00504                         if(otherMech == mechTarget)
00505                                 continue;
00506 
00507                         debugC3(tprintf
00508                                         ("C3RANGE-NETWORK (mech): Finding range from %d to %d.",
00509                                          mech->mynum, mechTarget->mynum));
00510 
00511                         c3Range = FaMechRange(otherMech, mechTarget);
00512                         inLOS =
00513                                 InLineOfSight(otherMech, mechTarget, MechX(mechTarget),
00514                                                           MechY(mechTarget), c3Range);
00515                 } else if((MechTargX(mech) > 0) && (MechTargY(mech) > 0)) {
00516                         mapX = MechTargX(mech);
00517                         mapY = MechTargY(mech);
00518                         map = getMap(mech->mapindex);
00519 
00520                         debugC3(tprintf
00521                                         ("C3RANGE-NETWORK (hex): Finding range from %d to %d %d.",
00522                                          mech->mynum, mapX, mapY));
00523 
00524                         MechTargZ(mech) = Elevation(map, mapX, mapY);
00525                         hexZ = ZSCALE * MechTargZ(mech);
00526                         MapCoordToRealCoord(mapX, mapY, &hexX, &hexY);
00527 
00528                         c3Range =
00529                                 FindRange(MechFX(otherMech), MechFY(otherMech),
00530                                                   MechFZ(otherMech), hexX, hexY, hexZ);
00531                         inLOS = LOS_NB(otherMech, NULL, mapX, mapY, c3Range);
00532                 } else {
00533                         continue;
00534                 }
00535 
00536                 if(inLOS && (c3Range < bestRange)) {
00537                         bestRange = c3Range;
00538                         *c3Ref = otherMech->mynum;
00539                 }
00540         }
00541 
00542         return bestRange;
00543 }
00544 
00545 void debugC3(char *msg)
00546 {
00547         if(DEBUG_C3)
00548                 SendDebug(msg);
00549 }

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