// Build a list of orders available for the selected structure. static std::vector<AVORDER> buildStructureOrderList(STRUCTURE *psStructure) { ASSERT_OR_RETURN(std::vector<AVORDER>(), StructIsFactory(psStructure), "BuildStructureOrderList: structure is not a factory"); //this can be hard-coded! std::vector<AVORDER> orders(2); orders[0].OrderIndex = 0;//DSO_REPAIR_LEVEL; orders[1].OrderIndex = 1;//DSO_ATTACK_LEVEL; return orders; }
// Build a list of orders available for the selected structure. static std::vector<AVORDER> buildStructureOrderList(STRUCTURE *psStructure) { //only valid for Factories (at the moment) ASSERT_OR_RETURN(std::vector<AVORDER>(), StructIsFactory(psStructure), "BuildStructureOrderList: structure is not a factory"); //this can be hard-coded! std::vector<AVORDER> orders(4); orders[0].OrderIndex = 1;//DSO_REPAIR_LEVEL; orders[1].OrderIndex = 2;//DSO_ATTACK_LEVEL; orders[2].OrderIndex = 5;//DSO_HALTTYPE; return orders; }
// ******************************************************************************************** bool scrSkGetFactoryCapacity(void) { SDWORD count = 0; STRUCTURE *psStructure; if (!stackPopParams(1, ST_STRUCTURE, &psStructure)) { return false; } if (psStructure && StructIsFactory(psStructure)) { count = psStructure->capacity; } scrFunctionResult.v.ival = count; if (!stackPushResult(VAL_INT, &scrFunctionResult)) { return false; } return true; }
// ******************************************************************************************** BOOL scrSkGetFactoryCapacity(void) { SDWORD count=0,structure; STRUCTURE *psStructure; if (!stackPopParams(1,ST_STRUCTURE, &structure)) { return FALSE; } psStructure = (STRUCTURE *) structure; if(psStructure && StructIsFactory(psStructure)) { count = ((FACTORY *)psStructure->pFunctionality)->capacity; } if (!stackPushResult(VAL_INT, count)) { return FALSE; } return TRUE; }
/*called when a Template is deleted in the Design screen*/ void deleteTemplateFromProduction(DROID_TEMPLATE *psTemplate, unsigned player, QUEUE_MODE mode) { STRUCTURE *psStruct; STRUCTURE *psList; //see if any factory is currently using the template for (unsigned i = 0; i < 2; ++i) { psList = NULL; switch (i) { case 0: psList = apsStructLists[player]; break; case 1: psList = mission.apsStructLists[player]; break; } for (psStruct = psList; psStruct != NULL; psStruct = psStruct->psNext) { if (StructIsFactory(psStruct)) { FACTORY *psFactory = &psStruct->pFunctionality->factory; if (psFactory->psAssemblyPoint->factoryInc < asProductionRun[psFactory->psAssemblyPoint->factoryType].size()) { ProductionRun &productionRun = asProductionRun[psFactory->psAssemblyPoint->factoryType][psFactory->psAssemblyPoint->factoryInc]; for (unsigned inc = 0; inc < productionRun.size(); ++inc) { if (productionRun[inc].psTemplate->multiPlayerID == psTemplate->multiPlayerID && mode == ModeQueue) { //just need to erase this production run entry productionRun.erase(productionRun.begin() + inc); --inc; } } } if (psFactory->psSubject == NULL) { continue; } // check not being built in the factory for the template player if (psTemplate->multiPlayerID == psFactory->psSubject->multiPlayerID && mode == ModeImmediate) { syncDebugStructure(psStruct, '<'); syncDebug("Clearing production"); // Clear the factory's subject, and returns power. cancelProduction(psStruct, ModeImmediate, false); // Check to see if anything left to produce. (Also calls cancelProduction again, if nothing left to produce, which is a no-op. But if other things are left to produce, doesn't call cancelProduction, so wouldn't return power without the explicit cancelProduction call above.) doNextProduction(psStruct, NULL, ModeImmediate); //tell the interface intManufactureFinished(psStruct); syncDebugStructure(psStruct, '>'); } } } } }
// Add the droid order screen. // Returns true if the form was displayed ok. // //changed to a BASE_OBJECT to accomodate the factories - AB 21/04/99 bool intAddOrder(BASE_OBJECT *psObj) { bool Animate = true; SECONDARY_STATE State; UWORD OrdIndex; UWORD Height, NumDisplayedOrders; UWORD NumButs; UWORD NumJustifyButs, NumCombineButs, NumCombineBefore; bool bLastCombine, bHidden; DROID *Droid; STRUCTURE *psStructure; if (bInTutorial) { // No RMB orders in tutorial!! return (false); } // Is the form already up? if (widgGetFromID(psWScreen, IDORDER_FORM) != NULL) { intRemoveOrderNoAnim(); Animate = false; } // Is the stats window up? if (widgGetFromID(psWScreen, IDSTAT_FORM) != NULL) { intRemoveStatsNoAnim(); Animate = false; } if (psObj) { if (psObj->type == OBJ_DROID) { Droid = (DROID *)psObj; psStructure = NULL; } else if (psObj->type == OBJ_STRUCTURE) { Droid = NULL; psStructure = (STRUCTURE *)psObj; psSelectedFactory = psStructure; ASSERT_OR_RETURN(false, StructIsFactory(psSelectedFactory), "Trying to select a %s as a factory!", objInfo((BASE_OBJECT *)psSelectedFactory)); } else { ASSERT(false, "Invalid object type"); Droid = NULL; psStructure = NULL; } } else { Droid = NULL; psStructure = NULL; } setWidgetsStatus(true); AvailableOrders.clear(); SelectedDroids.clear(); // Selected droid is a command droid? if ((Droid != NULL) && (Droid->droidType == DROID_COMMAND)) { // displaying for a command droid - ignore any other droids SelectedDroids.push_back(Droid); } else if (psStructure != NULL) { AvailableOrders = buildStructureOrderList(psStructure); if (AvailableOrders.empty()) { return false; } } // Otherwise build a list of selected droids. else if (!BuildSelectedDroidList()) { // If no droids selected then see if we were given a specific droid. if (Droid != NULL) { // and put it in the list. SelectedDroids.push_back(Droid); } } // Build a list of orders available for the list of selected droids. - if a factory has not been selected if (psStructure == NULL) { AvailableOrders = buildDroidOrderList(); if (AvailableOrders.empty()) { // If no orders then return; return false; } } WIDGET *parent = psWScreen->psForm; /* Create the basic form */ IntFormAnimated *orderForm = new IntFormAnimated(parent, Animate); // Do not animate the opening, if the window was already open. orderForm->id = IDORDER_FORM; orderForm->setGeometry(ORDER_X, ORDER_Y, ORDER_WIDTH, ORDER_HEIGHT); // Add the close button. W_BUTINIT sButInit; sButInit.formID = IDORDER_FORM; sButInit.id = IDORDER_CLOSE; sButInit.x = ORDER_WIDTH - CLOSE_WIDTH; sButInit.y = 0; sButInit.width = CLOSE_WIDTH; sButInit.height = CLOSE_HEIGHT; sButInit.pTip = _("Close"); sButInit.pDisplay = intDisplayImageHilight; sButInit.UserData = PACKDWORD_TRI(0, IMAGE_CLOSEHILIGHT , IMAGE_CLOSE); if (!widgAddButton(psWScreen, &sButInit)) { return false; } sButInit = W_BUTINIT(); sButInit.formID = IDORDER_FORM; sButInit.id = IDORDER_CLOSE + 1; sButInit.pDisplay = intDisplayButtonHilight; sButInit.y = ORDER_BUTY; Height = 0; NumDisplayedOrders = 0; for (unsigned j = 0; j < AvailableOrders.size() && NumDisplayedOrders < MAX_DISPLAYABLE_ORDERS; ++j) { OrdIndex = AvailableOrders[j].OrderIndex; // Get current order state. State = GetSecondaryStates(OrderButtons[OrdIndex].Order); // Get number of buttons. NumButs = OrderButtons[OrdIndex].NumButs; // Set actual number of buttons. OrderButtons[OrdIndex].AcNumButs = NumButs; // Handle special case for factory -> command droid assignment buttons. switch (OrderButtons[OrdIndex].Class) { case ORDBUTCLASS_FACTORY: NumButs = countAssignableFactories((UBYTE)selectedPlayer, FACTORY_FLAG); break; case ORDBUTCLASS_CYBORGFACTORY: NumButs = countAssignableFactories((UBYTE)selectedPlayer, CYBORG_FLAG); break; case ORDBUTCLASS_VTOLFACTORY: NumButs = countAssignableFactories((UBYTE)selectedPlayer, VTOL_FLAG); break; default: break; } sButInit.id = OrderButtons[OrdIndex].ButBaseID; NumJustifyButs = NumButs; bLastCombine = false; switch (OrderButtons[OrdIndex].ButJustify & ORD_JUSTIFY_MASK) { case ORD_JUSTIFY_LEFT: sButInit.x = ORDER_BUTX; break; case ORD_JUSTIFY_RIGHT: sButInit.x = orderForm->width() - ORDER_BUTX - (NumJustifyButs * GetImageWidth(IntImages, OrderButtons[OrdIndex].ButImageID[0]) + (NumJustifyButs - 1) * ORDER_BUTGAP); break; case ORD_JUSTIFY_CENTER: sButInit.x = (orderForm->width() - (NumJustifyButs * GetImageWidth(IntImages, OrderButtons[OrdIndex].ButImageID[0]) + (NumJustifyButs - 1) * ORDER_BUTGAP)) / 2; break; case ORD_JUSTIFY_COMBINE: // see how many are on this line before the button NumCombineBefore = 0; for (unsigned i = 0; i < j; ++i) { if ((OrderButtons[AvailableOrders[i].OrderIndex].ButJustify & ORD_JUSTIFY_MASK) == ORD_JUSTIFY_COMBINE) { NumCombineBefore += 1; } } NumCombineButs = (UWORD)(NumCombineBefore + 1); // now see how many in total for (unsigned i = j + 1; i < AvailableOrders.size(); ++i) { if ((OrderButtons[AvailableOrders[i].OrderIndex].ButJustify & ORD_JUSTIFY_MASK) == ORD_JUSTIFY_COMBINE) { NumCombineButs += 1; } } // get position on line NumCombineButs = (UWORD)(NumCombineButs - (NumCombineBefore - (NumCombineBefore % ORD_MAX_COMBINE_BUTS))); if (NumCombineButs >= ORD_MAX_COMBINE_BUTS) { // the buttons will fill the line sButInit.x = (SWORD)(ORDER_BUTX + (GetImageWidth(IntImages, OrderButtons[OrdIndex].ButImageID[0]) + ORDER_BUTGAP) * NumCombineBefore); } else { // center the buttons sButInit.x = orderForm->width() / 2 - (NumCombineButs * GetImageWidth(IntImages, OrderButtons[OrdIndex].ButImageID[0]) + (NumCombineButs - 1) * ORDER_BUTGAP) / 2; sButInit.x = (SWORD)(sButInit.x + (GetImageWidth(IntImages, OrderButtons[OrdIndex].ButImageID[0]) + ORDER_BUTGAP) * NumCombineBefore); } // see if need to start a new line of buttons if ((NumCombineBefore + 1) == (NumCombineButs % ORD_MAX_COMBINE_BUTS)) { bLastCombine = true; } break; } for (unsigned i = 0; i < OrderButtons[OrdIndex].AcNumButs; ++i) { sButInit.pTip = getDORDDescription(OrderButtons[OrdIndex].ButTips[i]); sButInit.width = (UWORD)GetImageWidth(IntImages, OrderButtons[OrdIndex].ButImageID[i]); sButInit.height = (UWORD)GetImageHeight(IntImages, OrderButtons[OrdIndex].ButImageID[i]); sButInit.UserData = PACKDWORD_TRI(OrderButtons[OrdIndex].ButGreyID[i], OrderButtons[OrdIndex].ButHilightID[i], OrderButtons[OrdIndex].ButImageID[i]); if (!widgAddButton(psWScreen, &sButInit)) { return false; } // Set the default state for the button. switch (OrderButtons[OrdIndex].ButType) { case ORD_BTYPE_RADIO: case ORD_BTYPE_BOOLEAN: if ((State & OrderButtons[OrdIndex].StateMask) == (UDWORD)OrderButtons[OrdIndex].States[i]) { widgSetButtonState(psWScreen, sButInit.id, WBUT_CLICKLOCK); } else { widgSetButtonState(psWScreen, sButInit.id, 0); } break; case ORD_BTYPE_BOOLEAN_DEPEND: if ((State & OrderButtons[OrdIndex].StateMask) == (UDWORD)OrderButtons[OrdIndex].States[i]) { widgSetButtonState(psWScreen, sButInit.id, WBUT_CLICKLOCK); } else { if (i == 0) { widgSetButtonState(psWScreen, sButInit.id, 0); } else { widgSetButtonState(psWScreen, sButInit.id, WBUT_DISABLE); } } break; case ORD_BTYPE_BOOLEAN_COMBINE: if (State & (UDWORD)OrderButtons[OrdIndex].States[i]) { widgSetButtonState(psWScreen, sButInit.id, WBUT_CLICKLOCK); } break; } // may not add a button if the factory doesn't exist bHidden = false; switch (OrderButtons[OrdIndex].Class) { case ORDBUTCLASS_FACTORY: if (!checkFactoryExists(selectedPlayer, FACTORY_FLAG, i)) { widgHide(psWScreen, sButInit.id); bHidden = true; } break; case ORDBUTCLASS_CYBORGFACTORY: if (!checkFactoryExists(selectedPlayer, CYBORG_FLAG, i)) { widgHide(psWScreen, sButInit.id); bHidden = true; } break; case ORDBUTCLASS_VTOLFACTORY: if (!checkFactoryExists(selectedPlayer, VTOL_FLAG, i)) { widgHide(psWScreen, sButInit.id); bHidden = true; } break; default: break; } if (!bHidden) { sButInit.x = (SWORD)(sButInit.x + sButInit.width + ORDER_BUTGAP); } sButInit.id++; } if (((OrderButtons[OrdIndex].ButJustify & ORD_JUSTIFY_MASK) != ORD_JUSTIFY_COMBINE) || bLastCombine) { sButInit.y = (SWORD)(sButInit.y + sButInit.height + ORDER_BUTGAP); Height = (UWORD)(Height + sButInit.height + ORDER_BUTGAP); } NumDisplayedOrders ++; } // Now we know how many orders there are we can resize the form accordingly. int newHeight = Height + CLOSE_HEIGHT + ORDER_BUTGAP; orderForm->setGeometry(orderForm->x(), ORDER_BOTTOMY - newHeight, orderForm->width(), newHeight); OrderUp = true; return true; }
void recvStructureInfo(NETQUEUE queue) { uint8_t player = 0; uint32_t structId = 0; uint32_t templateId = 0; uint8_t structureInfo; STRUCTURE * psStruct; DROID_TEMPLATE *psTempl = NULL; NETbeginDecode(queue, GAME_STRUCTUREINFO); NETuint8_t(&player); NETuint32_t(&structId); NETuint8_t(&structureInfo); if (structureInfo == STRUCTUREINFO_MANUFACTURE) { NETuint32_t(&templateId); if (templateId != 0) { psTempl = IdToTemplate(templateId, player); if (psTempl == NULL) { debug(LOG_SYNC, "Synch error, don't have tempate id %u, so can't change production of factory %u!", templateId, structId); } } } NETend(); psStruct = IdToStruct(structId, player); syncDebug("player%d,structId%u%c,structureInfo%u,templateId%u%c", player, structId, psStruct == NULL? '^' : '*', structureInfo, templateId, psTempl == NULL? '^' : '*'); if (psStruct == NULL) { debug(LOG_SYNC, "Couldn't find structure %u to change production.", structId); return; } CHECK_STRUCTURE(psStruct); if (StructIsFactory(psStruct)) { if (psStruct->pFunctionality->factory.pendingCount == 0) { ++psStruct->pFunctionality->factory.pendingCount; } if (--psStruct->pFunctionality->factory.pendingCount == 0) { // Subject is now synchronised, remove pending. psStruct->pFunctionality->factory.psSubjectPending = NULL; psStruct->pFunctionality->factory.statusPending = FACTORY_NOTHING_PENDING; } } syncDebugStructure(psStruct, '<'); switch (structureInfo) { case STRUCTUREINFO_MANUFACTURE: structSetManufacture(psStruct, psTempl, ModeImmediate); break; case STRUCTUREINFO_CANCELPRODUCTION: cancelProduction(psStruct, ModeImmediate); break; case STRUCTUREINFO_HOLDPRODUCTION: holdProduction(psStruct, ModeImmediate); break; case STRUCTUREINFO_RELEASEPRODUCTION: releaseProduction(psStruct, ModeImmediate); break; case STRUCTUREINFO_HOLDRESEARCH: holdResearch(psStruct, ModeImmediate); break; case STRUCTUREINFO_RELEASERESEARCH: releaseResearch(psStruct, ModeImmediate); break; default: debug(LOG_ERROR, "Invalid structureInfo %d", structureInfo); } syncDebugStructure(psStruct, '>'); CHECK_STRUCTURE(psStruct); }
// //////////////////////////////////////////////////////////////////////////// // throw a party when you win! bool multiplayerWinSequence(bool firstCall) { static Position pos; Position pos2; static UDWORD last=0; float rotAmount; STRUCTURE *psStruct; if(firstCall) { pos = cameraToHome(selectedPlayer,true); // pan the camera to home if not already doing so last =0; // stop all research CancelAllResearch(selectedPlayer); // stop all manufacture. for(psStruct=apsStructLists[selectedPlayer];psStruct;psStruct = psStruct->psNext) { if (StructIsFactory(psStruct)) { if (((FACTORY *)psStruct->pFunctionality)->psSubject)//check if active { cancelProduction(psStruct, ModeQueue); } } } } // rotate world if (MissionResUp && !getWarCamStatus()) { rotAmount = graphicsTimeAdjustedIncrement(MAP_SPIN_RATE / 12); player.r.y += rotAmount; } if(last > gameTime)last= 0; if((gameTime-last) < 500 ) // only if not done recently. { return true; } last = gameTime; if(rand()%3 == 0) { pos2=pos; pos2.x += (rand() % world_coord(8)) - world_coord(4); pos2.z += (rand() % world_coord(8)) - world_coord(4); if (pos2.x < 0) pos2.x = 128; if ((unsigned)pos2.x > world_coord(mapWidth)) pos2.x = world_coord(mapWidth); if (pos2.z < 0) pos2.z = 128; if ((unsigned)pos2.z > world_coord(mapHeight)) pos2.z = world_coord(mapHeight); addEffect(&pos2,EFFECT_FIREWORK,FIREWORK_TYPE_LAUNCHER,false,NULL,0); // throw up some fire works. } // show the score.. return true; }
/*called when a Template is deleted in the Design screen*/ void deleteTemplateFromProduction(DROID_TEMPLATE *psTemplate, unsigned player, QUEUE_MODE mode) { STRUCTURE *psStruct; STRUCTURE *psList; //see if any factory is currently using the template for (unsigned i = 0; i < 2; ++i) { psList = NULL; switch (i) { case 0: psList = apsStructLists[player]; break; case 1: psList = mission.apsStructLists[player]; break; } for (psStruct = psList; psStruct != NULL; psStruct = psStruct->psNext) { if (StructIsFactory(psStruct)) { FACTORY *psFactory = &psStruct->pFunctionality->factory; if (psFactory->psAssemblyPoint->factoryInc < asProductionRun[psFactory->psAssemblyPoint->factoryType].size()) { ProductionRun &productionRun = asProductionRun[psFactory->psAssemblyPoint->factoryType][psFactory->psAssemblyPoint->factoryInc]; for (unsigned inc = 0; inc < productionRun.size(); ++inc) { if (productionRun[inc].psTemplate->multiPlayerID == psTemplate->multiPlayerID && mode == ModeQueue) { //just need to erase this production run entry productionRun.erase(productionRun.begin() + inc); --inc; } } } if (psFactory->psSubject == NULL) { continue; } // check not being built in the factory for the template player if (psTemplate->multiPlayerID == psFactory->psSubject->multiPlayerID && mode == ModeImmediate) { syncDebugStructure(psStruct, '<'); syncDebug("Clearing production"); // Clear the factory's subject. psFactory->psSubject = NULL; if (player == productionPlayer) { //check to see if anything left to produce DROID_TEMPLATE *psNextTemplate = factoryProdUpdate(psStruct, NULL); //power is returned by factoryProdAdjust() if (psNextTemplate) { structSetManufacture(psStruct, psNextTemplate, ModeQueue); // ModeQueue because production lists aren't synchronised. } } //tell the interface intManufactureFinished(psStruct); syncDebugStructure(psStruct, '>'); } } } } }
void recvStructureInfo(NETQUEUE queue) { uint8_t player = 0; uint32_t structId = 0; uint32_t templateId = 0; uint8_t structureInfo; STRUCTURE *psStruct; DROID_TEMPLATE *psTempl = NULL; NETbeginDecode(queue, GAME_STRUCTUREINFO); NETuint8_t(&player); NETuint32_t(&structId); NETuint8_t(&structureInfo); if (structureInfo == STRUCTUREINFO_MANUFACTURE) { NETuint32_t(&templateId); if (templateId != 0) { // For autogames, where we want the AI to take us over, our templates are not setup... so let's use any AI's templates. if (!NetPlay.players[player].autoGame) { psTempl = IdToTemplate(templateId, player); } else { psTempl = IdToTemplate(templateId, ANYPLAYER); } if (psTempl == NULL) { debug(LOG_SYNC, "Synch error, don't have tempate id %u, so can't change production of factory %u!", templateId, structId); } } } NETend(); psStruct = IdToStruct(structId, player); syncDebug("player%d,structId%u%c,structureInfo%u,templateId%u%c", player, structId, psStruct == NULL ? '^' : '*', structureInfo, templateId, psTempl == NULL ? '^' : '*'); if (psStruct == NULL) { debug(LOG_SYNC, "Couldn't find structure %u to change production.", structId); return; } if (!canGiveOrdersFor(queue.index, psStruct->player)) { syncDebug("Wrong player."); return; } CHECK_STRUCTURE(psStruct); if (StructIsFactory(psStruct)) { popStatusPending(psStruct->pFunctionality->factory); } else if (psStruct->pStructureType->type == REF_RESEARCH) { popStatusPending(psStruct->pFunctionality->researchFacility); } syncDebugStructure(psStruct, '<'); switch (structureInfo) { case STRUCTUREINFO_MANUFACTURE: structSetManufacture(psStruct, psTempl, ModeImmediate); break; case STRUCTUREINFO_CANCELPRODUCTION: cancelProduction(psStruct, ModeImmediate, false); break; case STRUCTUREINFO_HOLDPRODUCTION: holdProduction(psStruct, ModeImmediate); break; case STRUCTUREINFO_RELEASEPRODUCTION: releaseProduction(psStruct, ModeImmediate); break; case STRUCTUREINFO_HOLDRESEARCH: holdResearch(psStruct, ModeImmediate); break; case STRUCTUREINFO_RELEASERESEARCH: releaseResearch(psStruct, ModeImmediate); break; default: debug(LOG_ERROR, "Invalid structureInfo %d", structureInfo); } syncDebugStructure(psStruct, '>'); CHECK_STRUCTURE(psStruct); }