// add a droid to a group void grpJoin(DROID_GROUP *psGroup, DROID *psDroid) { ASSERT(grpInitialized, "Group code not initialized yet"); ASSERT_OR_RETURN(, psGroup != NULL, "grpJoin: invalid group pointer" ); psGroup->refCount += 1; // if psDroid == NULL just increase the refcount don't add anything to the list if (psDroid != NULL) { if (psGroup->psList && psDroid->player != psGroup->psList->player) { ASSERT( false,"grpJoin: Cannot have more than one players droids in a group" ); return; } if (psDroid->psGroup != NULL) { grpLeave(psDroid->psGroup, psDroid); } psDroid->psGroup = psGroup; if (psDroid->droidType == DROID_TRANSPORTER) { ASSERT_OR_RETURN(, (psGroup->type == GT_NORMAL), "grpJoin: Cannot have two transporters in a group" ); psGroup->type = GT_TRANSPORTER; psDroid->psGrpNext = psGroup->psList; psGroup->psList = psDroid; } else if ((psDroid->droidType == DROID_COMMAND) &&
BOOL scrCBTransporterLandedB( void ) { SDWORD player; DROID_GROUP *psGroup; DROID *psTransporter, *psDroid, *psNext; BOOL retval; DROID **ppsTransp; if (!stackPopParams(3, ST_GROUP, &psGroup, VAL_INT, &player, VAL_REF|ST_DROID, &ppsTransp)) { debug(LOG_ERROR, "scrCBTransporterLandedB(): stack failed"); return false; } psTransporter = transporterGetScriptCurrent(); if ( (psTransporter == NULL) || (psTransporter->player != (UDWORD)player) ) { retval = false; } else { *ppsTransp = psTransporter; //return landed transporter /* if not selectedPlayer unload droids */ //if ( (UDWORD)player != selectedPlayer ) //{ /* transfer droids from transporter group to current group */ for(psDroid=psTransporter->psGroup->psList; psDroid; psDroid=psNext) { psNext = psDroid->psGrpNext; if ( psDroid != psTransporter ) { grpLeave( psTransporter->psGroup, psDroid ); grpJoin(psGroup, psDroid); } } //} retval = true; } scrFunctionResult.v.bval = retval; if (!stackPushResult(VAL_BOOL, &scrFunctionResult)) { debug(LOG_ERROR, "scrCBTransporterLandedB: push landed"); return false; } return true; }
// add a droid to a group at the end of the list void grpJoinEnd(DROID_GROUP *psGroup, DROID *psDroid) { DROID *psPrev, *psCurr; psGroup->refCount += 1; ASSERT((PTRVALID(psGroup, sizeof(DROID_GROUP)), "grpJoin: invalid group pointer")); // if psDroid == NULL just increase the refcount don't add anything to the list if (psDroid != NULL) { if (psGroup->psList && psDroid->player != psGroup->psList->player) { ASSERT((FALSE,"grpJoin: Cannot have more than one players droids in a group")); return; } if (psDroid->psGroup != NULL) { grpLeave(psDroid->psGroup, psDroid); } psDroid->psGroup = psGroup; if (psDroid->droidType == DROID_COMMAND) { ASSERT(((psGroup->type == GT_NORMAL) && (psGroup->psCommander == NULL), "grpJoin: Cannot have two command droids in a group")); psGroup->type = GT_COMMAND; psGroup->psCommander = psDroid; } else { // add the droid to the end of the list psPrev = NULL; psDroid->psGrpNext = NULL; for(psCurr = psGroup->psList; psCurr; psCurr=psCurr->psGrpNext) { psPrev = psCurr; } if (psPrev != NULL) { psPrev->psGrpNext = psDroid; } else { psGroup->psList = psDroid; } } } }
// release a ST_GROUP variable void scrvReleaseGroup(INTERP_VAL *psVal) { DROID_GROUP *psGroup; psGroup = (DROID_GROUP*)psVal->v.oval; grpReset(psGroup); ASSERT( psGroup->refCount == 1, "scrvReleaseGroup: ref count is wrong" ); // do a final grpLeave to free the group grpLeave(psGroup, NULL); }
// remove all droids from a group void grpReset(DROID_GROUP *psGroup) { DROID *psCurr, *psNext; ASSERT((PTRVALID(psGroup, sizeof(DROID_GROUP)), "grpReset: invalid droid group")); for(psCurr = psGroup->psList; psCurr; psCurr = psNext) { psNext = psCurr->psGrpNext; grpLeave(psGroup, psCurr); } }
// remove a droid from a group BOOL scrDroidLeaveGroup(void) { DROID *psDroid; if (!stackPopParams(1, ST_DROID, &psDroid)) { return FALSE; } if (psDroid->psGroup != NULL) { grpLeave(psDroid->psGroup, psDroid); } return TRUE; }
BOOL scrCBTransporterLanded( void ) { SDWORD player; DROID_GROUP *psGroup; DROID *psTransporter, *psDroid, *psNext; BOOL retval; if (!stackPopParams(2, ST_GROUP, &psGroup, VAL_INT, &player)) { return false; } psTransporter = transporterGetScriptCurrent(); if ( (psTransporter == NULL) || (psTransporter->player != (UDWORD)player) ) { retval = false; } else { /* if not selectedPlayer unload droids */ if ( (UDWORD)player != selectedPlayer ) { /* transfer droids from transporter group to current group */ for(psDroid=psTransporter->psGroup->psList; psDroid; psDroid=psNext) { psNext = psDroid->psGrpNext; if ( psDroid != psTransporter ) { grpLeave( psTransporter->psGroup, psDroid ); grpJoin(psGroup, psDroid); } } } retval = true; } scrFunctionResult.v.bval = retval; if (!stackPushResult(VAL_BOOL, &scrFunctionResult)) { return false; } return true; }
// add a droid to a group void grpJoin(DROID_GROUP *psGroup, DROID *psDroid) { psGroup->refCount += 1; ASSERT((PTRVALID(psGroup, sizeof(DROID_GROUP)), "grpJoin: invalid group pointer")); // if psDroid == NULL just increase the refcount don't add anything to the list if (psDroid != NULL) { if (psGroup->psList && psDroid->player != psGroup->psList->player) { ASSERT((FALSE,"grpJoin: Cannot have more than one players droids in a group")); return; } if (psDroid->psGroup != NULL) { grpLeave(psDroid->psGroup, psDroid); } psDroid->psGroup = psGroup; if (psDroid->droidType == DROID_TRANSPORTER) { ASSERT(((psGroup->type == GT_NORMAL), "grpJoin: Cannot have two transporters in a group")); psGroup->type = GT_TRANSPORTER; psDroid->psGrpNext = psGroup->psList; psGroup->psList = psDroid; } else if ((psDroid->droidType == DROID_COMMAND) && (psGroup->type != GT_TRANSPORTER)) { ASSERT(((psGroup->type == GT_NORMAL) && (psGroup->psCommander == NULL), "grpJoin: Cannot have two command droids in a group")); psGroup->type = GT_COMMAND; psGroup->psCommander = psDroid; } else { psDroid->psGrpNext = psGroup->psList; psGroup->psList = psDroid; } } }
// //////////////////////////////////////////////////////////////////////////// // receive droid information form other players. BOOL recvDroidInfo(NETQUEUE queue) { NETbeginDecode(queue, GAME_DROIDINFO); { QueuedDroidInfo info; memset(&info, 0x00, sizeof(info)); NETQueuedDroidInfo(&info); STRUCTURE_STATS *psStats = NULL; if (info.order == DORDER_BUILD || info.order == DORDER_LINEBUILD) { // Find structure target for (unsigned typeIndex = 0; typeIndex < numStructureStats; typeIndex++) { if (asStructureStats[typeIndex].ref == info.structRef) { psStats = asStructureStats + typeIndex; break; } } } if (info.subType) { syncDebug("Order=%s,%d(%d)", getDroidOrderName(info.order), info.destId, info.destType); } else { syncDebug("Order=%s,(%d,%d)", getDroidOrderName(info.order), info.x, info.y); } DROID_ORDER_DATA sOrder; memset(&sOrder, 0x00, sizeof(sOrder)); sOrder.order = info.order; sOrder.x = info.x; sOrder.y = info.y; sOrder.x2 = info.x2; sOrder.y2 = info.y2; sOrder.direction = info.direction; sOrder.psObj = processDroidTarget(info.destType, info.destId); sOrder.psStats = (BASE_STATS *)psStats; uint32_t num = 0; NETuint32_t(&num); for (unsigned n = 0; n < num; ++n) { // Get the next droid ID which is being given this order. uint32_t deltaDroidId = 0; NETuint32_t(&deltaDroidId); info.droidId += deltaDroidId; DROID *psDroid = NULL; if (!IdToDroid(info.droidId, ANYPLAYER, &psDroid)) { debug(LOG_NEVER, "Packet from %d refers to non-existent droid %u, [%s : p%d]", queue.index, info.droidId, isHumanPlayer(info.player) ? "Human" : "AI", info.player); syncDebug("Droid %d missing", info.droidId); continue; // Can't find the droid, so skip this droid. } CHECK_DROID(psDroid); syncDebugDroid(psDroid, '<'); psDroid->waitingForOwnReceiveDroidInfoMessage = false; /* * If the current order not is a command order and we are not a * commander yet are in the commander group remove us from it. */ if (hasCommander(psDroid)) { grpLeave(psDroid->psGroup, psDroid); } if (sOrder.psObj != TargetMissing) // Only do order if the target didn't die. { orderDroidBase(psDroid, &sOrder); } syncDebugDroid(psDroid, '>'); CHECK_DROID(psDroid); } } NETend(); return true; }
/** Receive info about a droid that is being unloaded from a transporter * * \sa sendDroidEmbark(),recvDroidEmbark(),sendDroidDisEmbark() */ BOOL recvDroidDisEmbark(NETQUEUE queue) { DROID *psFoundDroid = NULL, *psTransporterDroid = NULL; DROID *psCheckDroid = NULL; NETbeginDecode(queue, GAME_DROIDDISEMBARK); { uint8_t player; uint32_t droidID; uint32_t transporterID; Position pos; NETuint8_t(&player); NETuint32_t(&droidID); NETuint32_t(&transporterID); NETPosition(&pos); NETend(); // find the transporter first if (!IdToDroid(transporterID, player, &psTransporterDroid)) { // Possible it already died? (sync error?) debug(LOG_WARNING, "player's %d transport droid %d wasn't found?", player, transporterID); return false; } // we need to find the droid *in* the transporter psCheckDroid = psTransporterDroid ->psGroup->psList; while (psCheckDroid) { // is this the one we want? if( psCheckDroid->id == droidID) { psFoundDroid = psCheckDroid; break; } // not found, so check next one in *group* psCheckDroid = psCheckDroid->psGrpNext; } // don't continue if we couldn't find it. if (!psFoundDroid) { // I don't think this could ever be possible...but debug(LOG_ERROR, "Couldn't find droid %d to disembark from player %d's transporter?", droidID, player); return false; } // remove it from the transporter grpLeave(psFoundDroid->psGroup, psFoundDroid); // and add it back to the bloody droid list addDroid(psFoundDroid, apsDroidLists); // Add it back into the world at the x/y droidSetPrecisePosition(psFoundDroid, pos); if (!droidOnMap(psFoundDroid)) { debug(LOG_ERROR, "droid %d disembarked was NOT on map?", psFoundDroid->id); return false; } updateDroidOrientation(psFoundDroid); // Initialise the movement data initDroidMovement(psFoundDroid); } return true; }